Commit 094b5c3d authored by Simon Kelley's avatar Simon Kelley

Fix crash in DNSSEC code when attempting to verify large RRs.

parent 32678045
...@@ -19,6 +19,9 @@ version 2.73 ...@@ -19,6 +19,9 @@ version 2.73
the answers given by --interface-name. Note that reverse queries the answers given by --interface-name. Note that reverse queries
(ie looking for names, given addresses) are not affected. (ie looking for names, given addresses) are not affected.
Thanks to Michael Gorbach for the suggestion. Thanks to Michael Gorbach for the suggestion.
Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids
for the bug report.
version 2.72 version 2.72
......
...@@ -456,16 +456,27 @@ static u16 *get_desc(int type) ...@@ -456,16 +456,27 @@ static u16 *get_desc(int type)
/* Return bytes of canonicalised rdata, when the return value is zero, the remaining /* Return bytes of canonicalised rdata, when the return value is zero, the remaining
data, pointed to by *p, should be used raw. */ data, pointed to by *p, should be used raw. */
static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen,
unsigned char **p, u16 **desc) unsigned char **p, u16 **desc)
{ {
int d = **desc; int d = **desc;
(*desc)++;
/* No more data needs mangling */ /* No more data needs mangling */
if (d == (u16)-1) if (d == (u16)-1)
return 0; {
/* If there's more data than we have space for, just return what fits,
we'll get called again for more chunks */
if (end - *p > bufflen)
{
memcpy(buff, *p, bufflen);
*p += bufflen;
return bufflen;
}
return 0;
}
(*desc)++;
if (d == 0 && extract_name(header, plen, p, buff, 1, 0)) if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
/* domain-name, canonicalise */ /* domain-name, canonicalise */
...@@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int ...@@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
if (left1 != 0) if (left1 != 0)
memmove(buff1, buff1 + len1 - left1, left1); memmove(buff1, buff1 + len1 - left1, left1);
if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0) if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0)
{ {
quit = 1; quit = 1;
len1 = end1 - p1; len1 = end1 - p1;
...@@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int ...@@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
if (left2 != 0) if (left2 != 0)
memmove(buff2, buff2 + len2 - left2, left2); memmove(buff2, buff2 + len2 - left2, left2);
if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0) if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0)
{ {
quit = 1; quit = 1;
len2 = end2 - p2; len2 = end2 - p2;
...@@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* canonicalise rdata and calculate length of same, use name buffer as workspace */ /* canonicalise rdata and calculate length of same, use name buffer as workspace */
cp = p; cp = p;
dp = rr_desc; dp = rr_desc;
for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg); for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg);
len += end - cp; len += end - cp;
len = htons(len); len = htons(len);
hash->update(ctx, 2, (unsigned char *)&len); hash->update(ctx, 2, (unsigned char *)&len);
...@@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in ...@@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* Now canonicalise again and digest. */ /* Now canonicalise again and digest. */
cp = p; cp = p;
dp = rr_desc; dp = rr_desc;
while ((seg = get_rdata(header, plen, end, name, &cp, &dp))) while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)))
hash->update(ctx, seg, (unsigned char *)name); hash->update(ctx, seg, (unsigned char *)name);
if (cp != end) if (cp != end)
hash->update(ctx, end - cp, cp); hash->update(ctx, end - cp, cp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment