summaryrefslogtreecommitdiffstats
path: root/contrib/bind/named
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-05-02 11:04:44 +0000
committerpeter <peter@FreeBSD.org>1998-05-02 11:04:44 +0000
commita8be3d081819e16ac57be46b9e0b78f5be1b17aa (patch)
tree76a80c58089c1715382da2bc9fa04ef91349fa3e /contrib/bind/named
parentc8a064d4002b5c8ccd5b2dc2e8b2c91eaa958fc8 (diff)
parent58ca52f41726d17758909ddafba7b6b6766c789c (diff)
downloadFreeBSD-src-a8be3d081819e16ac57be46b9e0b78f5be1b17aa.zip
FreeBSD-src-a8be3d081819e16ac57be46b9e0b78f5be1b17aa.tar.gz
This commit was generated by cvs2svn to compensate for changes in r35618,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/bind/named')
-rw-r--r--contrib/bind/named/named-xfer.c62
-rw-r--r--contrib/bind/named/ns_ncache.c34
-rw-r--r--contrib/bind/named/ns_req.c56
-rw-r--r--contrib/bind/named/ns_resp.c156
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;
}
OpenPOWER on IntegriCloud