summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 37e1808)
raw | patch | inline | side by side (parent: 37e1808)
author | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Wed, 16 Jun 2010 12:08:58 +0000 (14:08 +0200) | ||
committer | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Wed, 16 Jun 2010 12:08:58 +0000 (14:08 +0200) |
src/utils_dns.c | patch | blob | history | |
src/utils_dns.h | patch | blob | history |
diff --git a/src/utils_dns.c b/src/utils_dns.c
index 2348be24db05d55c5b1d6b6ad000ce8108594701..66798e2b02e127ee6af71805eb80281f6b7a00e5 100644 (file)
--- 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 efc790319cebea5e3253cad748de71d4e8923aaa..56213afa18bc800035fafa88b149120edf266b4f 100644 (file)
--- a/src/utils_dns.h
+++ b/src/utils_dns.h
# include <pcap.h>
#endif
+#define DNS_MSG_HDR_SZ 12
+
#define T_MAX 65536
#define OP_MAX 16
#define C_MAX 65536