diff options
author | Guy Harris <guy@alum.mit.edu> | 2000-04-12 06:59:28 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2000-04-12 06:59:28 +0000 |
commit | 8512fc4d739dd902f60e29a0a1b76e3c8b47ea8d (patch) | |
tree | b5c710fb945f4171c5ff1d1509e14ee7d4ef8dd9 | |
parent | df5f3b52ceb29d5be3feb40180c7f22ea2f60728 (diff) |
Catch "loops" in compressed DNS names the same way the BSD DNS resolver,
and BIND, do, by counting the number of characters we look at and, if
when we see a pointer, we see we've already looked at as many characters
as there are in the DNS packet, we conclude that we're looping.
Also, check for pointers that point past the end of the packet (not just
past the end of the captured portion of the packet, i.e. cases where we
didn't capture all of the packet, but cases where the packet is actually
malformed).
svn path=/trunk/; revision=1830
-rw-r--r-- | packet-dns.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/packet-dns.c b/packet-dns.c index f744baa3ac..c82625943a 100644 --- a/packet-dns.c +++ b/packet-dns.c @@ -1,7 +1,7 @@ /* packet-dns.c * Routines for DNS packet disassembly * - * $Id: packet-dns.c,v 1.41 2000/04/04 06:17:28 guy Exp $ + * $Id: packet-dns.c,v 1.42 2000/04/12 06:59:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -330,6 +330,8 @@ get_dns_name(const u_char *pd, int offset, int dns_data_offset, const u_char *dptr = dp; char *np = name; int len = -1; + int chars_processed = 0; + int data_size = pi.len - dns_data_offset; u_int component_len; maxname--; /* reserve space for the trailing '\0' */ @@ -340,6 +342,7 @@ get_dns_name(const u_char *pd, int offset, int dns_data_offset, offset++; if (component_len == 0) break; + chars_processed++; switch (component_len & 0xc0) { case 0x00: @@ -361,6 +364,7 @@ get_dns_name(const u_char *pd, int offset, int dns_data_offset, component_len--; dp++; offset++; + chars_processed++; } break; @@ -370,18 +374,30 @@ get_dns_name(const u_char *pd, int offset, int dns_data_offset, case 0xc0: /* Pointer. */ - /* XXX - check to make sure we aren't looping, by keeping track - of how many characters are in the DNS packet, and of how many - characters we've looked at, and quitting if the latter - becomes bigger than the former. */ if (!BYTES_ARE_IN_FRAME(offset, 1)) goto overflow; offset = dns_data_offset + (((component_len & ~0xc0) << 8) | (*dp++)); + chars_processed++; + /* If "len" is negative, we are still working on the original name, not something pointed to by a pointer, and so we should set "len" to the length of the original name. */ if (len < 0) len = dp - dptr; + + if (offset >= pi.len) { + strcpy(name, "<Name contains a pointer that goes past the end of the packet>"); + return len; + } + + /* If we've looked at every character in the message, this pointer + will make us look at some character again, which means we're + looping. */ + if (chars_processed >= data_size) { + strcpy(name, "<Name contains a pointer that loops>"); + return len; + } + dp = pd + offset; break; /* now continue processing from there */ } |