aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind/lib/irs/dns_ho.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/lib/irs/dns_ho.c')
-rw-r--r--contrib/bind/lib/irs/dns_ho.c70
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;
}
}