diff options
Diffstat (limited to 'contrib/bind/lib/irs/dns_ho.c')
-rw-r--r-- | contrib/bind/lib/irs/dns_ho.c | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/contrib/bind/lib/irs/dns_ho.c b/contrib/bind/lib/irs/dns_ho.c index 7d64e5332bb0..6c0a6e7373fe 100644 --- a/contrib/bind/lib/irs/dns_ho.c +++ b/contrib/bind/lib/irs/dns_ho.c @@ -52,7 +52,7 @@ /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$Id: dns_ho.c,v 1.35 2002/05/08 01:49:27 marka Exp $"; +static const char rcsid[] = "$Id: dns_ho.c,v 1.39 2002/06/27 03:56:32 marka Exp $"; #endif /* LIBC_SCCS and not lint */ /* Imports. */ @@ -74,6 +74,7 @@ static const char rcsid[] = "$Id: dns_ho.c,v 1.35 2002/05/08 01:49:27 marka Exp #include <resolv.h> #include <stdio.h> #include <string.h> +#include <syslog.h> #include <isc/memcluster.h> #include <irs.h> @@ -161,7 +162,7 @@ static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai); static void map_v4v6_hostent(struct hostent *hp, char **bp, - int *len); + char *ep); static void addrsort(res_state, char **, int); static struct hostent * gethostans(struct irs_ho *this, const u_char *ansbuf, int anslen, @@ -404,15 +405,12 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) q->answer = q->qbuf.buf; q->anslen = sizeof(q->qbuf); q->next = q2; - if ((pvt->res->options & RES_NO_BITSTRING) != 0) - q->action = RESTGT_IGNORE; - else - q->action = RESTGT_DOALWAYS; + q->action = RESTGT_DOALWAYS; q2->qclass = C_IN; q2->qtype = T_PTR; q2->answer = q2->qbuf.buf; q2->anslen = sizeof(q2->qbuf); - if ((pvt->res->options & RES_NO_NIBBLE) != 0) + if ((pvt->res->options & RES_NO_NIBBLE2) != 0) q2->action = RESTGT_IGNORE; else q2->action = RESTGT_AFTERFAILURE; @@ -441,11 +439,12 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) case AF_INET6: if (q->action != RESTGT_IGNORE) { qp = q->qname; - qp += SPRINTF((qp, "\\[x")); - for (n = 0; n < IN6ADDRSZ; n++) - qp += SPRINTF((qp, "%02x", uaddr[n])); - SPRINTF((qp, "/128].%s", - res_get_bitstringsuffix(pvt->res))); + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + } + strcpy(qp, res_get_nibblesuffix(pvt->res)); } if (q2->action != RESTGT_IGNORE) { qp = q2->qname; @@ -454,7 +453,7 @@ ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf)); } - strcpy(qp, res_get_nibblesuffix(pvt->res)); + strcpy(qp, res_get_nibblesuffix2(pvt->res)); } break; default: @@ -1081,7 +1080,7 @@ gethostans(struct irs_ho *this, struct addrinfo **ret_aip, const struct addrinfo *pai) { struct pvt *pvt = (struct pvt *)this->private; - int type, class, buflen, ancount, qdcount, n, haveanswer, had_error; + int type, class, ancount, qdcount, n, haveanswer, had_error; int error = NETDB_SUCCESS, arcount; int (*name_ok)(const char *); const HEADER *hp; @@ -1090,7 +1089,7 @@ gethostans(struct irs_ho *this, const u_char *cp; const char *tname; const char *hname; - char *bp, **ap, **hap; + char *bp, *ep, **ap, **hap; char tbuf[MAXDNAME+1]; struct addrinfo sentinel, *cur, ai; const u_char *arp = NULL; @@ -1133,13 +1132,13 @@ gethostans(struct irs_ho *this, qdcount = ntohs(hp->qdcount); arcount = ntohs(hp->arcount); bp = pvt->hostbuf; - buflen = sizeof 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, buflen); + 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); @@ -1163,7 +1162,6 @@ gethostans(struct irs_ho *this, pvt->host.h_name = bp; hname = bp; bp += n; - buflen -= n; /* The qname can be abbreviated, but hname is now absolute. */ qname = pvt->host.h_name; } @@ -1176,7 +1174,7 @@ gethostans(struct irs_ho *this, haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(ansbuf, eom, cp, bp, buflen); + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { had_error++; continue; @@ -1197,6 +1195,15 @@ gethostans(struct irs_ho *this, eor = cp + n; if ((qtype == T_A || qtype == T_AAAA || qtype == ns_t_a6 || qtype == T_ANY) && 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 : "."); + } n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { had_error++; @@ -1209,10 +1216,9 @@ gethostans(struct irs_ho *this, *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) { + if (n > (ep - bp) || n > MAXHOSTNAMELEN) { had_error++; continue; } @@ -1220,7 +1226,6 @@ gethostans(struct irs_ho *this, pvt->host.h_name = bp; hname = bp; bp += n; - buflen -= n; continue; } if (type == ns_t_dname) { @@ -1256,7 +1261,7 @@ gethostans(struct irs_ho *this, cp += n; n = strlen(t) + 1; /* for the \0 */ - if (n > buflen) { + if (n > (ep - bp)) { had_error++; continue; } @@ -1266,7 +1271,6 @@ gethostans(struct irs_ho *this, else hname = bp; bp += n; - buflen -= n; continue; } @@ -1292,14 +1296,13 @@ gethostans(struct irs_ho *this, } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen) { + if (n > (ep - bp)) { had_error++; continue; } strcpy(bp, tbuf); tname = bp; bp += n; - buflen -= n; continue; } if (qtype == T_ANY) { @@ -1323,7 +1326,7 @@ gethostans(struct irs_ho *this, cp += n; continue; } - n = dn_expand(ansbuf, eor, cp, bp, buflen); + n = dn_expand(ansbuf, eor, cp, bp, ep - bp); if (n < 0 || !maybe_hnok(pvt->res, bp) || n >= MAXHOSTNAMELEN) { had_error++; @@ -1341,7 +1344,6 @@ gethostans(struct irs_ho *this, if (n != -1) { n = strlen(bp) + 1; /* for the \0 */ bp += n; - buflen -= n; } break; case ns_t_a6: { @@ -1441,7 +1443,6 @@ gethostans(struct irs_ho *this, pvt->host.h_name = bp; hname = bp; bp += nn; - buflen -= nn; } /* Ensure alignment. */ bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & @@ -1495,15 +1496,14 @@ gethostans(struct irs_ho *this, haveanswer); if (pvt->host.h_name == NULL) { n = strlen(qname) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) + if (n > (ep - bp) || 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); + map_v4v6_hostent(&pvt->host, &bp, ep); RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); return (&pvt->host); } else { @@ -1577,7 +1577,7 @@ add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) } static void -map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) { +map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) { char **ap; if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) @@ -1590,17 +1590,15 @@ map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) { if (i != 0) i = sizeof(align) - i; - if (*lenp < (i + IN6ADDRSZ)) { + if ((ep - *bpp) < (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; } } |