diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-05 11:16:52 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-05 11:16:52 +0000 |
commit | 8b7ec32a2fd246b2356a056abd7d17ebac81edcf (patch) | |
tree | d1f45646d5f83de88fb8d793fca42756a286f48a /src/dns | |
parent | 55278ebb7ec49b6fa741f44e6076167740f1e50b (diff) | |
download | gnunet-8b7ec32a2fd246b2356a056abd7d17ebac81edcf.tar.gz gnunet-8b7ec32a2fd246b2356a056abd7d17ebac81edcf.zip |
-bugfixes
Diffstat (limited to 'src/dns')
-rw-r--r-- | src/dns/dnsparser.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c index e02ce73fb..40870c597 100644 --- a/src/dns/dnsparser.c +++ b/src/dns/dnsparser.c | |||
@@ -74,12 +74,14 @@ GNUNET_NETWORK_STRUCT_END | |||
74 | * @param udp_payload_length length of udp_payload | 74 | * @param udp_payload_length length of udp_payload |
75 | * @param off pointer to the offset of the name to parse in the udp_payload (to be | 75 | * @param off pointer to the offset of the name to parse in the udp_payload (to be |
76 | * incremented by the size of the name) | 76 | * incremented by the size of the name) |
77 | * @param depth current depth of our recursion (to prevent stack overflow) | ||
77 | * @return name as 0-terminated C string on success, NULL if the payload is malformed | 78 | * @return name as 0-terminated C string on success, NULL if the payload is malformed |
78 | */ | 79 | */ |
79 | static char * | 80 | static char * |
80 | parse_name (const char *udp_payload, | 81 | parse_name (const char *udp_payload, |
81 | size_t udp_payload_length, | 82 | size_t udp_payload_length, |
82 | size_t *off) | 83 | size_t *off, |
84 | unsigned int depth) | ||
83 | { | 85 | { |
84 | const uint8_t *input = (const uint8_t *) udp_payload; | 86 | const uint8_t *input = (const uint8_t *) udp_payload; |
85 | char *ret; | 87 | char *ret; |
@@ -114,13 +116,18 @@ parse_name (const char *udp_payload, | |||
114 | } | 116 | } |
115 | else if ((64 | 128) == (len & (64 | 128)) ) | 117 | else if ((64 | 128) == (len & (64 | 128)) ) |
116 | { | 118 | { |
119 | if (depth > 32) | ||
120 | goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */ | ||
117 | /* pointer to string */ | 121 | /* pointer to string */ |
118 | if (*off + 1 > udp_payload_length) | 122 | if (*off + 1 > udp_payload_length) |
119 | goto error; | 123 | goto error; |
120 | xoff = ((len - (64 | 128)) << 8) + input[*off+1]; | 124 | xoff = ((len - (64 | 128)) << 8) + input[*off+1]; |
121 | xstr = parse_name (udp_payload, | 125 | xstr = parse_name (udp_payload, |
122 | udp_payload_length, | 126 | udp_payload_length, |
123 | &xoff); | 127 | &xoff, |
128 | depth + 1); | ||
129 | if (NULL == xstr) | ||
130 | goto error; | ||
124 | GNUNET_asprintf (&tmp, | 131 | GNUNET_asprintf (&tmp, |
125 | "%s%s.", | 132 | "%s%s.", |
126 | ret, | 133 | ret, |
@@ -128,6 +135,8 @@ parse_name (const char *udp_payload, | |||
128 | GNUNET_free (ret); | 135 | GNUNET_free (ret); |
129 | GNUNET_free (xstr); | 136 | GNUNET_free (xstr); |
130 | ret = tmp; | 137 | ret = tmp; |
138 | if (strlen (ret) > udp_payload_length) | ||
139 | goto error; /* we are looping (building an infinite string) */ | ||
131 | *off += 2; | 140 | *off += 2; |
132 | /* pointers always terminate names */ | 141 | /* pointers always terminate names */ |
133 | break; | 142 | break; |
@@ -168,7 +177,7 @@ parse_query (const char *udp_payload, | |||
168 | 177 | ||
169 | name = parse_name (udp_payload, | 178 | name = parse_name (udp_payload, |
170 | udp_payload_length, | 179 | udp_payload_length, |
171 | off); | 180 | off, 0); |
172 | if (NULL == name) | 181 | if (NULL == name) |
173 | return GNUNET_SYSERR; | 182 | return GNUNET_SYSERR; |
174 | q->name = name; | 183 | q->name = name; |
@@ -206,7 +215,7 @@ parse_record (const char *udp_payload, | |||
206 | 215 | ||
207 | name = parse_name (udp_payload, | 216 | name = parse_name (udp_payload, |
208 | udp_payload_length, | 217 | udp_payload_length, |
209 | off); | 218 | off, 0); |
210 | if (NULL == name) | 219 | if (NULL == name) |
211 | return GNUNET_SYSERR; | 220 | return GNUNET_SYSERR; |
212 | r->name = name; | 221 | r->name = name; |
@@ -231,7 +240,7 @@ parse_record (const char *udp_payload, | |||
231 | old_off = *off; | 240 | old_off = *off; |
232 | r->data.hostname = parse_name (udp_payload, | 241 | r->data.hostname = parse_name (udp_payload, |
233 | udp_payload_length, | 242 | udp_payload_length, |
234 | off); | 243 | off, 0); |
235 | if ( (NULL == r->data.hostname) || | 244 | if ( (NULL == r->data.hostname) || |
236 | (old_off + r->data_len != *off) ) | 245 | (old_off + r->data_len != *off) ) |
237 | return GNUNET_SYSERR; | 246 | return GNUNET_SYSERR; |
@@ -241,10 +250,10 @@ parse_record (const char *udp_payload, | |||
241 | r->data.soa = GNUNET_malloc (sizeof (struct GNUNET_DNSPARSER_SoaRecord)); | 250 | r->data.soa = GNUNET_malloc (sizeof (struct GNUNET_DNSPARSER_SoaRecord)); |
242 | r->data.soa->mname = parse_name (udp_payload, | 251 | r->data.soa->mname = parse_name (udp_payload, |
243 | udp_payload_length, | 252 | udp_payload_length, |
244 | off); | 253 | off, 0); |
245 | r->data.soa->rname = parse_name (udp_payload, | 254 | r->data.soa->rname = parse_name (udp_payload, |
246 | udp_payload_length, | 255 | udp_payload_length, |
247 | off); | 256 | off, 0); |
248 | if ( (NULL == r->data.soa->mname) || | 257 | if ( (NULL == r->data.soa->mname) || |
249 | (NULL == r->data.soa->rname) || | 258 | (NULL == r->data.soa->rname) || |
250 | (*off + sizeof (soa) > udp_payload_length) ) | 259 | (*off + sizeof (soa) > udp_payload_length) ) |
@@ -269,7 +278,7 @@ parse_record (const char *udp_payload, | |||
269 | r->data.mx->preference = ntohs (mxpref); | 278 | r->data.mx->preference = ntohs (mxpref); |
270 | r->data.mx->mxhost = parse_name (udp_payload, | 279 | r->data.mx->mxhost = parse_name (udp_payload, |
271 | udp_payload_length, | 280 | udp_payload_length, |
272 | off); | 281 | off, 0); |
273 | if (old_off + r->data_len != *off) | 282 | if (old_off + r->data_len != *off) |
274 | return GNUNET_SYSERR; | 283 | return GNUNET_SYSERR; |
275 | return GNUNET_OK; | 284 | return GNUNET_OK; |