diff options
author | peter <peter@FreeBSD.org> | 1998-05-02 11:04:44 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-05-02 11:04:44 +0000 |
commit | 58ca52f41726d17758909ddafba7b6b6766c789c (patch) | |
tree | bf60fe39ce5fbbf445ea2ef5462024ee99d3613b /contrib/bind/named | |
parent | 47492cc08d0e2630b8140cc5b25e635606858ad8 (diff) | |
download | FreeBSD-src-58ca52f41726d17758909ddafba7b6b6766c789c.zip FreeBSD-src-58ca52f41726d17758909ddafba7b6b6766c789c.tar.gz |
Import ISC bind v4.9.7-T1B as a reference. We may need this if we update
-stable to 4.9.7 instead of 8.1.2 for whatever reason.
Diffstat (limited to 'contrib/bind/named')
-rw-r--r-- | contrib/bind/named/named-xfer.c | 62 | ||||
-rw-r--r-- | contrib/bind/named/ns_ncache.c | 34 | ||||
-rw-r--r-- | contrib/bind/named/ns_req.c | 56 | ||||
-rw-r--r-- | contrib/bind/named/ns_resp.c | 156 |
4 files changed, 241 insertions, 67 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; diff --git a/contrib/bind/named/ns_ncache.c b/contrib/bind/named/ns_ncache.c index ff76bca..ccacf61 100644 --- a/contrib/bind/named/ns_ncache.c +++ b/contrib/bind/named/ns_ncache.c @@ -21,6 +21,13 @@ #ifdef NCACHE +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return; \ + } \ + } while (0) + void cache_n_resp(msg, msglen) u_char *msg; @@ -28,7 +35,7 @@ cache_n_resp(msg, msglen) { register struct databuf *dp; HEADER *hp; - u_char *cp; + u_char *cp, *eom, *rdatap; char dname[MAXDNAME]; int n; int type, class; @@ -36,19 +43,22 @@ cache_n_resp(msg, msglen) int Vcode; #endif int flags; + u_int dlen; nameserIncr(from_addr.sin_addr, nssRcvdNXD); hp = (HEADER *)msg; cp = msg+HFIXEDSZ; + eom = msg + msglen; - n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); + n = dn_expand(msg, eom, cp, dname, sizeof dname); if (n < 0) { dprintf(1, (ddt, "Query expand name failed:cache_n_resp\n")); hp->rcode = FORMERR; return; } cp += n; + BOUNDS_CHECK(cp, 2 * INT16SZ); GETSHORT(type, cp); GETSHORT(class, cp); dprintf(1, (ddt, @@ -76,13 +86,14 @@ cache_n_resp(msg, msglen) if (hp->rcode == NXDOMAIN) type = T_SOA; - /* store ther SOA record */ - n = dn_skipname(tp, msg + msglen); + /* store their SOA record */ + n = dn_skipname(tp, eom); if (n < 0) { dprintf(3, (ddt, "ncache: form error\n")); return; } tp += n; + BOUNDS_CHECK(tp, 3 * INT16SZ + INT32SZ); GETSHORT(atype, tp); /* type */ if (atype != T_SOA) { dprintf(3, (ddt, @@ -91,10 +102,12 @@ cache_n_resp(msg, msglen) } tp += INT16SZ; /* class */ GETLONG(ttl, tp); /* ttl */ - tp += INT16SZ; /* dlen */ + GETSHORT(dlen, tp); /* dlen */ + BOUNDS_CHECK(tp, dlen); + rdatap = tp; /* origin */ - n = dn_expand(msg, msg + msglen, tp, (char*)data, len); + n = dn_expand(msg, eom, tp, (char*)data, len); if (n < 0) { dprintf(3, (ddt, "ncache: form error 2\n")); return; @@ -113,10 +126,17 @@ cache_n_resp(msg, msglen) n = strlen((char*)cp1) + 1; cp1 += n; len -= n; - bcopy(tp, cp1, n = 5 * INT32SZ); + n = 5 * INT32SZ; + BOUNDS_CHECK(tp, n); + bcopy(tp, cp1, n); /* serial, refresh, retry, expire, min */ cp1 += n; len -= n; + tp += n; + if (tp != rdatap + dlen) { + dprintf(3, (ddt, "ncache: form error 2\n")); + return; + } /* store the zone of the soa record */ n = dn_expand(msg, msg + msglen, cp, (char*)cp1, len); if (n < 0) { diff --git a/contrib/bind/named/ns_req.c b/contrib/bind/named/ns_req.c index 0ed1296..bd59bab 100644 --- a/contrib/bind/named/ns_req.c +++ b/contrib/bind/named/ns_req.c @@ -1,6 +1,6 @@ #if !defined(lint) && !defined(SABER) static char sccsid[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91"; -static char rcsid[] = "$Id: ns_req.c,v 8.28 1997/06/01 20:34:34 vixie Exp $"; +static char rcsid[] = "$Id: ns_req.c,v 8.29 1998/04/07 04:59:45 vixie Exp $"; #endif /* not lint */ /* @@ -328,6 +328,11 @@ req_notify(hp, cpp, eom, msg, from) hp->rcode = FORMERR; return (Finish); } + if (*cpp + 2 * INT16SZ > eom) { + dprintf(1, (ddt, "FORMERR notify too short")); + hp->rcode = FORMERR; + return (Finish); + } *cpp += n; GETSHORT(type, *cpp); GETSHORT(class, *cpp); @@ -461,13 +466,13 @@ req_query(hp, cpp, eom, qsp, buflenp, msglenp, msg, dfd, from) return (Finish); } *cpp += n; - GETSHORT(type, *cpp); - GETSHORT(class, *cpp); - if (*cpp > eom) { + if (*cpp + 2 * INT16SZ > eom) { dprintf(1, (ddt, "FORMERR Query message length short\n")); hp->rcode = FORMERR; return (Finish); } + GETSHORT(type, *cpp); + GETSHORT(class, *cpp); if (*cpp < eom) { dprintf(6, (ddt,"message length > received message\n")); *msglenp = *cpp - msg; @@ -990,6 +995,11 @@ req_iquery(hp, cpp, eom, buflenp, msg, from) return (Finish); } *cpp += n; + if (*cpp + 3 * INT16SZ + INT32SZ > eom) { + dprintf(1, (ddt, "FORMERR IQuery message too short")); + hp->rcode = FORMERR; + return (Finish); + } GETSHORT(type, *cpp); GETSHORT(class, *cpp); *cpp += INT32SZ; /* ttl */ @@ -1007,7 +1017,7 @@ req_iquery(hp, cpp, eom, buflenp, msg, from) switch (type) { case T_A: #ifndef INVQ - if (!fake_iquery) + if (!fake_iquery || dlen != INT32SZ) return (Refuse); #endif #ifdef INVQ @@ -1021,7 +1031,10 @@ req_iquery(hp, cpp, eom, buflenp, msg, from) dprintf(1, (ddt, "req: IQuery class %d type %d\n", class, type)); fname = (char *)msg + HFIXEDSZ; - bcopy(fname, anbuf, alen = (char *)*cpp - fname); + alen = (char *)*cpp - fname; + if ((size_t)alen > sizeof anbuf) + return (Refuse); + bcopy(fname, anbuf, alen); data = anbuf + alen - dlen; *cpp = (u_char *)fname; *buflenp -= HFIXEDSZ; @@ -1068,6 +1081,10 @@ req_iquery(hp, cpp, eom, buflenp, msg, from) return (Finish); } *cpp += n; + if (*cpp + 2 * INT16SZ > dnbuf + *buflenp) { + hp->tc = 1; + return (Finish); + } PUTSHORT((u_int16_t)dp->d_type, *cpp); PUTSHORT((u_int16_t)dp->d_class, *cpp); *buflenp -= n; @@ -1256,6 +1273,8 @@ make_rr(name, dp, buf, buflen, doadd) } buflen -= RRFIXEDSZ; + if (buflen < 0) + return (-1); #if defined(RETURNSOA) && defined(NCACHE) if (dp->d_rcode) { name = (char *)dp->d_data; @@ -1269,6 +1288,8 @@ make_rr(name, dp, buf, buflen, doadd) return (-1); cp = buf + n; buflen -= n; + if (buflen < 0) + return (-1); PUTSHORT((u_int16_t)type, cp); PUTSHORT((u_int16_t)dp->d_class, cp); PUTLONG(ttl, cp); @@ -1308,6 +1329,8 @@ make_rr(name, dp, buf, buflen, doadd) return (-1); cp += n; buflen -= type == T_SOA ? n + 5 * INT32SZ : n; + if (buflen < 0) + return (-1); cp1 += strlen((char *)cp1) + 1; n = dn_comp((char *)cp1, cp, buflen, dnptrs, edp); if (n < 0) @@ -1326,10 +1349,10 @@ make_rr(name, dp, buf, buflen, doadd) /* cp1 == our data/ cp == data of RR */ cp1 = dp->d_data; - if ((buflen -= INT16SZ) < 0) - return (-1); - /* copy order */ + buflen -= INT16SZ; + if (buflen < 0) + return (-1); bcopy(cp1, cp, INT16SZ); cp += INT16SZ; cp1 += INT16SZ; @@ -1337,6 +1360,9 @@ make_rr(name, dp, buf, buflen, doadd) dprintf(1, (ddt, "current size n = %u\n", n)); /* copy preference */ + buflen -= INT16SZ; + if (buflen < 0) + return (-1); bcopy(cp1, cp, INT16SZ); cp += INT16SZ; cp1 += INT16SZ; @@ -1345,6 +1371,9 @@ make_rr(name, dp, buf, buflen, doadd) /* Flags */ n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + return (-1); dprintf(1, (ddt, "size of n at flags = %d\n", n)); *cp++ = n; bcopy(cp1,cp,n); @@ -1355,6 +1384,9 @@ make_rr(name, dp, buf, buflen, doadd) /* Service */ n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + return (-1); *cp++ = n; bcopy(cp1,cp,n); cp += n; @@ -1364,6 +1396,9 @@ make_rr(name, dp, buf, buflen, doadd) /* Regexp */ n = *cp1++; + buflen -= n + 1; + if (buflen < 0) + return (-1); *cp++ = n; bcopy(cp1,cp,n); cp += n; @@ -1402,6 +1437,9 @@ make_rr(name, dp, buf, buflen, doadd) cp1 += INT16SZ; if (type == T_SRV) { + buflen -= INT16SZ*2; + if (buflen < 0) + return (-1); bcopy(cp1, cp, INT16SZ*2); cp += INT16SZ*2; cp1 += INT16SZ*2; diff --git a/contrib/bind/named/ns_resp.c b/contrib/bind/named/ns_resp.c index d0f3221..d48da23 100644 --- a/contrib/bind/named/ns_resp.c +++ b/contrib/bind/named/ns_resp.c @@ -1,6 +1,6 @@ #if !defined(lint) && !defined(SABER) static char sccsid[] = "@(#)ns_resp.c 4.65 (Berkeley) 3/3/91"; -static char rcsid[] = "$Id: ns_resp.c,v 8.38 1997/06/01 20:34:34 vixie Exp vixie $"; +static char rcsid[] = "$Id: ns_resp.c,v 8.41 1998/04/07 04:59:45 vixie Exp $"; #endif /* not lint */ /* @@ -132,7 +132,8 @@ struct flush_set { static void rrsetadd __P((struct flush_set *, char *, struct databuf *)), rrsetupdate __P((struct flush_set *, int flags)), - flushrrset __P((struct flush_set *)); + flushrrset __P((struct flush_set *)), + free_flushset __P((struct flush_set *)); static int rrsetcmp __P((char *, struct db_list *)), check_root __P((void)), check_ns __P((void)), @@ -239,7 +240,7 @@ ns_resp(msg, msglen) register struct databuf *ns, *ns2; register u_char *cp; u_char *eom = msg + msglen; - struct flush_set *flushset; + struct flush_set *flushset = NULL; struct sockaddr_in *nsa; struct databuf *nsp[NSMAX]; int i, c, n, qdcount, ancount, aucount, nscount, arcount, arfirst; @@ -264,8 +265,6 @@ ns_resp(msg, msglen) struct fwdinfo *fwd; char *tname = NULL; - free_related_additional(); - nameserIncr(from_addr.sin_addr, nssRcvdR); nsp[0] = NULL; hp = (HEADER *) msg; @@ -302,6 +301,10 @@ ns_resp(msg, msglen) goto formerr; } cp += n; + if (cp + 2 * INT16SZ > eom) { + formerrmsg = outofDataQuery; + goto formerr; + } GETSHORT(qtype, cp); GETSHORT(qclass, cp); if (!ns_nameok(qname, qclass, response_trans, @@ -581,16 +584,12 @@ ns_resp(msg, msglen) goto formerr; } tp += n; - GETSHORT(type, tp); - if (tp >= eom) { + if (tp + 2 * INT16SZ > eom) { formerrmsg = outofDataAuth; goto formerr; } + GETSHORT(type, tp); GETSHORT(class, tp); - if (tp >= eom) { - formerrmsg = outofDataAuth; - goto formerr; - } if (!ns_nameok(name, class, response_trans, ns_ownercontext(type, response_trans), name, from_addr.sin_addr)) { @@ -645,6 +644,7 @@ ns_resp(msg, msglen) u_int16_t type, class, dlen; u_int32_t serial; u_char *tp = cp; + u_char *rdatap; n = dn_expand(msg, eom, tp, name, sizeof name); if (n < 0) { @@ -652,14 +652,15 @@ ns_resp(msg, msglen) goto formerr; } tp += n; /* name */ + if (tp + 3 * INT16SZ + INT32SZ > eom) { + formerrmsg = outofDataAnswer; + goto formerr; + } GETSHORT(type, tp); /* type */ GETSHORT(class, tp); /* class */ tp += INT32SZ; /* ttl */ GETSHORT(dlen, tp); /* dlen */ - if (tp >= eom) { - formerrmsg = outofDataAnswer; - goto formerr; - } + rdatap = tp; /* start of rdata */ if (!ns_nameok(name, class, response_trans, ns_ownercontext(type, response_trans), name, from_addr.sin_addr)) { @@ -675,10 +676,6 @@ ns_resp(msg, msglen) formerrmsg = msgbuf; goto formerr; } - if ((u_int)dlen < (5 * INT32SZ)) { - formerrmsg = dlenUnderrunAnswer; - goto formerr; - } if (0 >= (n = dn_skipname(tp, eom))) { formerrmsg = skipnameFailedAnswer; @@ -690,7 +687,16 @@ ns_resp(msg, msglen) goto formerr; } tp += n; /* rname */ + if (tp + 5 * INT32SZ > eom) { + formerrmsg = dlenUnderrunAnswer; + goto formerr; + } GETLONG(serial, tp); + tp += 4 * INT32SZ; /* Skip rest of SOA. */ + if ((u_int)(tp - rdatap) != dlen) { + formerrmsg = dlenOverrunAnswer; + goto formerr; + } qserial_answer(qp, serial); qremove(qp); @@ -786,12 +792,18 @@ ns_resp(msg, msglen) maybe_free(&tname); if (cp >= eom) { + free_related_additional(); + if (flushset != NULL) + free_flushset(flushset); formerrmsg = outofDataFinal; goto formerr; } n = rrextract(msg, msglen, cp, &dp, name, sizeof name, &tname); if (n < 0) { + free_related_additional(); maybe_free(&tname); + if (flushset != NULL) + free_flushset(flushset); formerrmsg = outofDataFinal; goto formerr; } @@ -921,13 +933,11 @@ ns_resp(msg, msglen) } rrsetadd(flushset, name, dp); } + free_related_additional(); maybe_free(&tname); if (flushset) { rrsetupdate(flushset, dbflags); - for (i = 0; i < count; i++) - if (flushset[i].fs_name) - free(flushset[i].fs_name); - free((char*)flushset); + free_flushset(flushset); } if (lastwascname && !externalcname) syslog(LOG_DEBUG, "%s (%s)", danglingCname, aname); @@ -1365,6 +1375,14 @@ ns_resp(msg, msglen) return; } +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + hp->rcode = FORMERR; \ + return (-1); \ + } \ + } while (0) + static int rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) u_char *msg; @@ -1375,7 +1393,7 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) int namelen; char **tnamep; { - register u_char *cp; + register u_char *cp, *eom, *rdatap; register int n; int class, type, dlen, n1; u_int32_t ttl; @@ -1389,15 +1407,19 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) *dpp = NULL; cp = rrp; - if ((n = dn_expand(msg, msg + msglen, cp, dname, namelen)) < 0) { + eom = msg + msglen; + if ((n = dn_expand(msg, eom, cp, dname, namelen)) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp); GETSHORT(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; if (!ns_nameok(dname, class, response_trans, ns_ownercontext(type, response_trans), dname, from_addr.sin_addr)) { @@ -1456,8 +1478,7 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) case T_MR: case T_NS: case T_PTR: - n = dn_expand(msg, msg + msglen, cp, - (char *)data, sizeof data); + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); if (n < 0) { hp->rcode = FORMERR; return (-1); @@ -1483,8 +1504,7 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) context = mailname_ctx; /* FALLTHROUGH */ soa_rp_minfo: - n = dn_expand(msg, msg + msglen, cp, - (char *)data, sizeof data); + n = dn_expand(msg, eom, cp, (char *)data, sizeof data); if (n < 0) { hp->rcode = FORMERR; return (-1); @@ -1495,11 +1515,15 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) return (-1); } cp += n; + /* + * The next use of 'cp' is dn_expand(), so we don't have + * to BOUNDS_CHECK() here. + */ cp1 = data + (n = strlen((char *)data) + 1); n1 = sizeof(data) - n; if (type == T_SOA) n1 -= 5 * INT32SZ; - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); + n = dn_expand(msg, eom, cp, (char *)cp1, n1); if (n < 0) { hp->rcode = FORMERR; return (-1); @@ -1516,7 +1540,9 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) cp += n; cp1 += strlen((char *)cp1) + 1; if (type == T_SOA) { - bcopy(cp, cp1, n = 5 * INT32SZ); + n = 5 * INT32SZ; + BOUNDS_CHECK(cp, n); + bcopy(cp, cp1, n); cp += n; cp1 += n; } @@ -1526,30 +1552,37 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) case T_NAPTR: /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); bcopy(cp, data, INT16SZ*2); cp1 = 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 */ + BOUNDS_CHECK(cp, 1); n = *cp++; + BOUNDS_CHECK(cp, n); *cp1++ = n; bcopy(cp, cp1, n); cp += n; cp1 += n; /* Regexp */ + BOUNDS_CHECK(cp, 1); n = *cp++; + BOUNDS_CHECK(cp, n); *cp1++ = n; bcopy(cp, cp1, n); cp += n; cp1 += n; /* Replacement */ - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, + n = dn_expand(msg, eom, cp, (char *)cp1, sizeof data - (cp1 - data)); if (n < 0) { hp->rcode = FORMERR; @@ -1574,19 +1607,21 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) case T_RT: case T_SRV: /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); bcopy(cp, data, INT16SZ); cp1 = data + INT16SZ; cp += INT16SZ; if (type == T_SRV) { /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); bcopy(cp, cp1, INT16SZ*2); cp1 += INT16SZ*2; cp += INT16SZ*2; } /* get name */ - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, + n = dn_expand(msg, eom, cp, (char *)cp1, sizeof data - (cp1 - data)); if (n < 0) { hp->rcode = FORMERR; @@ -1611,13 +1646,14 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) case T_PX: /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); bcopy(cp, data, INT16SZ); cp1 = data + INT16SZ; cp += INT16SZ; /* get MAP822 name */ - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, - sizeof data - INT16SZ); + n = dn_expand(msg, eom, cp, (char *)cp1, + sizeof data - INT16SZ); if (n < 0) { hp->rcode = FORMERR; return (-1); @@ -1628,9 +1664,13 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) return (-1); } cp += n; + /* + * The next use of 'cp' is dn_expand(), so we don't have + * to BOUNDS_CHECK() here. + */ cp1 += (n = strlen((char *)cp1) + 1); n1 = sizeof(data) - n; - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); + n = dn_expand(msg, eom, cp, (char *)cp1, n1); if (n < 0) { hp->rcode = FORMERR; return (-1); @@ -1653,6 +1693,7 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) /* This code is similar to that in db_load.c. */ /* Skip coveredType, alg, labels */ + BOUNDS_CHECK(cp, INT16SZ + 1 + 1 + 3*INT32SZ); cp1 = cp + INT16SZ + 1 + 1; GETLONG(origTTL, cp1); GETLONG(exptime, cp1); @@ -1697,23 +1738,31 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) /* 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; /* then the signer's name */ - n = dn_expand(msg, msg + msglen, cp, - (char *)cp1, (sizeof data) - 18); - if (n < 0) + n = dn_expand(msg, eom, cp, (char *)cp1, (sizeof data) - 18); + if (n < 0) { + hp->rcode = FORMERR; return (-1); + } cp += n; cp1 += strlen((char*)cp1)+1; /* finally, we copy over the variable-length signature. Its size is the total data length, minus what we copied. */ + if (18 + (u_int)n > dlen) { + hp->rcode = FORMERR; + return (-1); + } 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; @@ -1728,6 +1777,18 @@ rrextract(msg, msglen, rrp, dpp, dname, namelen, tnamep) dprintf(3, (ddt, "unknown type %d\n", type)); return ((cp - rrp) + dlen); } + + if (cp > eom) { + hp->rcode = FORMERR; + return (-1); + } + if ((u_int)(cp - rdatap) != dlen) { + dprintf(3, (ddt, + "encoded rdata length is %u, but actual length was %u", + dlen, (u_int)(cp - rdatap))); + hp->rcode = FORMERR; + return (-1); + } if (n > MAXDATA) { dprintf(1, (ddt, "update type %d: %d bytes is too much data\n", @@ -3063,6 +3124,17 @@ flushrrset(fs) db_free(dp); } +static void +free_flushset(flushset) + struct flush_set *flushset; +{ + struct flush_set *fs; + + for (fs = flushset; fs->fs_name != NULL; fs++) + free(fs->fs_name); + free((char *)flushset); +} + /* * This is best thought of as a "cache invalidate" function. * It is called whenever a piece of data is determined to have @@ -3125,8 +3197,10 @@ add_related_additional(name) if (num_related >= MAX_RELATED - 1) return; for (i = 0; i < num_related; i++) - if (strcasecmp(name, related[i]) == 0) + if (strcasecmp(name, related[i]) == 0) { + free(name); return; + } related[num_related++] = name; } |