From 6079f1d8f9ac3f88e439184b05786c45effeb99d Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Wed, 16 Jun 2010 14:08:58 +0200 Subject: [PATCH] src/utils_dns.c: Import "rfc1035NameUnpack" from dnstop-20080321. --- src/utils_dns.c | 29 +++++++++++++++++++++-------- src/utils_dns.h | 2 ++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/utils_dns.c b/src/utils_dns.c index 2348be24..66798e2b 100644 --- a/src/utils_dns.c +++ b/src/utils_dns.c @@ -291,13 +291,18 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns off_t no = 0; unsigned char c; size_t len; - assert(ns > 0); + static int loop_detect = 0; + if (loop_detect > 2) + return 4; /* compression loop */ + if (ns <= 0) + return 4; /* probably compression loop */ do { if ((*off) >= sz) break; c = *(buf + (*off)); if (c > 191) { /* blasted compression */ + int rc; unsigned short s; off_t ptr; memcpy(&s, buf + (*off), sizeof(s)); @@ -305,18 +310,23 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns (*off) += sizeof(s); /* Sanity check */ if ((*off) >= sz) - return 1; + return 1; /* message too short */ ptr = s & 0x3FFF; /* Make sure the pointer is inside this message */ if (ptr >= sz) - return 2; - return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no); + return 2; /* bad compression ptr */ + if (ptr < DNS_MSG_HDR_SZ) + return 2; /* bad compression ptr */ + loop_detect++; + rc = rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no); + loop_detect--; + return rc; } else if (c > RFC1035_MAXLABELSZ) { /* * "(The 10 and 01 combinations are reserved for future use.)" */ + return 3; /* reserved label/compression flags */ break; - return 3; } else { (*off)++; len = (size_t) c; @@ -324,15 +334,18 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns break; if (len > (ns - 1)) len = ns - 1; - if ((*off) + len > sz) /* message is too short */ - return 4; + if ((*off) + len > sz) + return 4; /* message is too short */ + if (no + len + 1 > ns) + return 5; /* qname would overflow name buffer */ memcpy(name + no, buf + (*off), len); (*off) += len; no += len; *(name + (no++)) = '.'; } } while (c > 0); - *(name + no - 1) = '\0'; + if (no > 0) + *(name + no - 1) = '\0'; /* make sure we didn't allow someone to overflow the name buffer */ assert(no <= ns); return 0; diff --git a/src/utils_dns.h b/src/utils_dns.h index efc79031..56213afa 100644 --- a/src/utils_dns.h +++ b/src/utils_dns.h @@ -42,6 +42,8 @@ # include #endif +#define DNS_MSG_HDR_SZ 12 + #define T_MAX 65536 #define OP_MAX 16 #define C_MAX 65536 -- 2.11.0