From: serassio <> Date: Sun, 23 Jan 2005 21:59:06 +0000 (+0000) Subject: Bug #1136: Internal DNS sometimes truncates host names in reverse (PTR) X-Git-Tag: SQUID_3_0_PRE4~894 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c837c65562bee30d72cfd0b904f3adaef9af3edc;p=thirdparty%2Fsquid.git Bug #1136: Internal DNS sometimes truncates host names in reverse (PTR) lookups Compressed hostnames was not dealt with proper, only saving the data of the initial string + 2 bytes. --- diff --git a/lib/rfc1035.c b/lib/rfc1035.c index 05db4762fa..44180b9daf 100644 --- a/lib/rfc1035.c +++ b/lib/rfc1035.c @@ -1,6 +1,6 @@ /* - * $Id: rfc1035.c,v 1.34 2005/01/23 14:55:45 serassio Exp $ + * $Id: rfc1035.c,v 1.35 2005/01/23 14:59:06 serassio Exp $ * * Low level DNS protocol routines * AUTHOR: Duane Wessels @@ -299,7 +299,7 @@ rfc1035HeaderUnpack(const char *buf, size_t sz, off_t * off, rfc1035_header * h) * Returns 0 (success) or 1 (error) */ static int -rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns, int rdepth) +rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, unsigned short *rdlength, char *name, size_t ns, int rdepth) { off_t no = 0; unsigned char c; @@ -324,7 +324,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns /* Make sure the pointer is inside this message */ if (ptr >= sz) return 1; - return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no, rdepth + 1); + return rfc1035NameUnpack(buf, sz, &ptr, rdlength, name + no, ns - no, rdepth + 1); } else if (c > RFC1035_MAXLABELSZ) { /* * "(The 10 and 01 combinations are reserved for future use.)" @@ -343,6 +343,8 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns (*off) += len; no += len; *(name + (no++)) = '.'; + if (rdlength) + *rdlength += len + 1; } } while (c > 0 && no < ns); if (no) @@ -369,8 +371,9 @@ rfc1035RRUnpack(const char *buf, size_t sz, off_t * off, rfc1035_rr * RR) { unsigned short s; unsigned int i; + unsigned short rdlength; off_t rdata_off; - if (rfc1035NameUnpack(buf, sz, off, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) { + if (rfc1035NameUnpack(buf, sz, off, NULL, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) { RFC1035_UNPACK_DEBUG; memset(RR, '\0', sizeof(*RR)); return 1; @@ -395,7 +398,8 @@ rfc1035RRUnpack(const char *buf, size_t sz, off_t * off, rfc1035_rr * RR) RR->ttl = ntohl(i); memcpy(&s, buf + (*off), sizeof(s)); (*off) += sizeof(s); - if ((*off) + ntohs(s) > sz) { + rdlength = ntohs(s); + if ((*off) + rdlength > sz) { /* * We got a truncated packet. 'dnscache' truncates UDP * replies at 512 octets, as per RFC 1035. @@ -404,31 +408,33 @@ rfc1035RRUnpack(const char *buf, size_t sz, off_t * off, rfc1035_rr * RR) memset(RR, '\0', sizeof(*RR)); return 1; } - RR->rdlength = ntohs(s); + RR->rdlength = rdlength; switch (RR->type) { case RFC1035_TYPE_PTR: RR->rdata = malloc(RFC1035_MAXHOSTNAMESZ); rdata_off = *off; - if (rfc1035NameUnpack(buf, sz, &rdata_off, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0)) + RR->rdlength = 0; /* Filled in by rfc1035NameUnpack */ + if (rfc1035NameUnpack(buf, sz, &rdata_off, &RR->rdlength, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0)) return 1; - if (rdata_off != ((*off) + RR->rdlength)) { + if (rdata_off != ((*off) + rdlength)) { /* * This probably doesn't happen for valid packets, but * I want to make sure that NameUnpack doesn't go beyond * the RDATA area. */ RFC1035_UNPACK_DEBUG; + free(RR->rdata); memset(RR, '\0', sizeof(*RR)); return 1; } break; case RFC1035_TYPE_A: default: - RR->rdata = malloc(RR->rdlength); - memcpy(RR->rdata, buf + (*off), RR->rdlength); + RR->rdata = malloc(rdlength); + memcpy(RR->rdata, buf + (*off), rdlength); break; } - (*off) += RR->rdlength; + (*off) += rdlength; assert((*off) <= sz); return 0; }