aboutsummaryrefslogtreecommitdiff
path: root/src/dns
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-05 11:16:52 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-05 11:16:52 +0000
commit8b7ec32a2fd246b2356a056abd7d17ebac81edcf (patch)
treed1f45646d5f83de88fb8d793fca42756a286f48a /src/dns
parent55278ebb7ec49b6fa741f44e6076167740f1e50b (diff)
downloadgnunet-8b7ec32a2fd246b2356a056abd7d17ebac81edcf.tar.gz
gnunet-8b7ec32a2fd246b2356a056abd7d17ebac81edcf.zip
-bugfixes
Diffstat (limited to 'src/dns')
-rw-r--r--src/dns/dnsparser.c25
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 */
79static char * 80static char *
80parse_name (const char *udp_payload, 81parse_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;