Lines 110-116
Link Here
|
110 |
int nrec; |
110 |
int nrec; |
111 |
int cnt; |
111 |
int cnt; |
112 |
|
112 |
|
113 |
u_char response[2048]; |
113 |
u_char *responsebuf; |
|
|
114 |
size_t responselen; |
114 |
|
115 |
|
115 |
int dns_len; |
116 |
int dns_len; |
116 |
|
117 |
|
Lines 127-137
Link Here
|
127 |
char name_buf[ NS_MAXDNAME ]; |
128 |
char name_buf[ NS_MAXDNAME ]; |
128 |
int prio; |
129 |
int prio; |
129 |
|
130 |
|
130 |
int rdlen; |
131 |
size_t rdlen; |
131 |
const u_char *rdata, *rdata_end; |
132 |
const u_char *rdata; |
132 |
|
133 |
|
|
|
134 |
#if HAVE_DECL_RES_NINIT |
133 |
void *res_spec; |
135 |
void *res_spec; |
134 |
struct __res_state *res_state; |
136 |
struct __res_state *res_state; |
|
|
137 |
#endif |
135 |
|
138 |
|
136 |
SPF_ASSERT_NOTNULL(spf_dns_server); |
139 |
SPF_ASSERT_NOTNULL(spf_dns_server); |
137 |
|
140 |
|
Lines 140-149
Link Here
|
140 |
SPF_ASSERT_NOTNULL(spfhook); |
143 |
SPF_ASSERT_NOTNULL(spfhook); |
141 |
#endif |
144 |
#endif |
142 |
|
145 |
|
|
|
146 |
#if HAVE_DECL_RES_NINIT |
143 |
res_spec = pthread_getspecific(res_state_key); |
147 |
res_spec = pthread_getspecific(res_state_key); |
144 |
if (res_spec == NULL) { |
148 |
if (res_spec == NULL) { |
145 |
res_state = (struct __res_state *) |
149 |
res_state = (struct __res_state *) |
146 |
malloc(sizeof(struct __res_state)); |
150 |
malloc(sizeof(struct __res_state)); |
|
|
151 |
memset(res_state, 0, sizeof(struct __res_state)); |
147 |
if (res_ninit(res_state) != 0) { |
152 |
if (res_ninit(res_state) != 0) { |
148 |
SPF_error("Failed to call res_ninit()"); |
153 |
SPF_error("Failed to call res_ninit()"); |
149 |
} |
154 |
} |
Lines 152-171
Link Here
|
152 |
else { |
157 |
else { |
153 |
res_state = (struct __res_state *)res_spec; |
158 |
res_state = (struct __res_state *)res_spec; |
154 |
} |
159 |
} |
|
|
160 |
#endif |
161 |
|
162 |
responselen = 2048; |
163 |
responsebuf = (u_char *)malloc(responselen); |
164 |
memset(responsebuf, 0, responselen); |
165 |
|
166 |
/* |
167 |
* Retry the lookup until our response buffer is big enough. |
168 |
* |
169 |
* This loop repeats until either we fail a lookup or we succeed. |
170 |
* The size of the response buffer is monotonic increasing, so eventually we |
171 |
* must either succeed, or we try to malloc more RAM than we can. |
172 |
* |
173 |
* The Linux man pages do not describe res_nquery adequately. Solaris says: |
174 |
* |
175 |
* The res_nquery() and res_query() routines return a length that may be bigger |
176 |
* than anslen. In that case, retry the query with a larger buf. The answer to the |
177 |
* second query may be larger still], so it is recommended that you supply a buf |
178 |
* larger than the answer returned by the previous query. answer must be large |
179 |
* enough to receive a maximum UDP response from the server or parts of the answer |
180 |
* will be silently discarded. The default maximum UDP response size is 512 bytes. |
181 |
*/ |
182 |
for (;;) { |
155 |
|
183 |
|
156 |
/* |
184 |
/* |
157 |
* try resolving the name |
185 |
* try resolving the name |
158 |
*/ |
186 |
*/ |
159 |
#if HAVE_DECL_RES_NINIT |
187 |
#if HAVE_DECL_RES_NINIT |
160 |
dns_len = res_nquery(res_state, domain, ns_c_in, rr_type, |
188 |
dns_len = res_nquery(res_state, domain, ns_c_in, rr_type, |
161 |
response, sizeof(response)); |
189 |
responsebuf, responselen); |
162 |
#else |
190 |
#else |
163 |
dns_len = res_query(domain, ns_c_in, rr_type, |
191 |
dns_len = res_query(domain, ns_c_in, rr_type, |
164 |
response, sizeof(response)); |
192 |
responsebuf, responselen); |
165 |
#endif |
193 |
#endif |
166 |
|
194 |
|
167 |
if ( dns_len < 0 ) { |
195 |
if ( dns_len < 0 ) { |
|
|
196 |
/* We failed to perform a lookup. */ |
168 |
/* This block returns unconditionally. */ |
197 |
/* This block returns unconditionally. */ |
|
|
198 |
free(responsebuf); |
169 |
if ( spf_dns_server->debug ) |
199 |
if ( spf_dns_server->debug ) |
170 |
SPF_debugf( "query failed: err = %d %s (%d): %s", |
200 |
SPF_debugf( "query failed: err = %d %s (%d): %s", |
171 |
dns_len, hstrerror( SPF_h_errno ), SPF_h_errno, |
201 |
dns_len, hstrerror( SPF_h_errno ), SPF_h_errno, |
Lines 178-183
Link Here
|
178 |
return SPF_dns_rr_new_init(spf_dns_server, |
208 |
return SPF_dns_rr_new_init(spf_dns_server, |
179 |
domain, rr_type, 0, SPF_h_errno); |
209 |
domain, rr_type, 0, SPF_h_errno); |
180 |
} |
210 |
} |
|
|
211 |
else if (dns_len > responselen) { |
212 |
/* We managed a lookup but our buffer was too small. */ |
213 |
responselen = dns_len + (dns_len >> 1); |
214 |
#if 0 |
215 |
/* Sanity-trap - we should never hit this. */ |
216 |
if (responselen > 1048576) { /* One megabyte. */ |
217 |
free(responsebuf); |
218 |
return SPF_dns_rr_new_init(spf_dns_server, |
219 |
domain, rr_type, 0, SPF_h_errno); |
220 |
} |
221 |
#endif |
222 |
responsebuf = realloc(responsebuf, responselen); |
223 |
} |
224 |
else { |
225 |
/* We managed a lookup, and our buffer was large enough. */ |
226 |
responselen = dns_len; |
227 |
break; |
228 |
} |
229 |
} |
181 |
|
230 |
|
182 |
/* |
231 |
/* |
183 |
* initialize stuff |
232 |
* initialize stuff |
Lines 185-196
Link Here
|
185 |
spfrr = SPF_dns_rr_new_init(spf_dns_server, |
234 |
spfrr = SPF_dns_rr_new_init(spf_dns_server, |
186 |
domain, rr_type, 0, NETDB_SUCCESS); |
235 |
domain, rr_type, 0, NETDB_SUCCESS); |
187 |
|
236 |
|
188 |
err = ns_initparse( response, dns_len, &ns_handle ); |
237 |
err = ns_initparse(responsebuf, responselen, &ns_handle); |
189 |
|
238 |
|
190 |
if ( err < 0 ) { /* 0 or -1 */ |
239 |
if ( err < 0 ) { /* 0 or -1 */ |
191 |
if ( spf_dns_server->debug ) |
240 |
if ( spf_dns_server->debug ) |
192 |
SPF_debugf( "ns_initparse failed: err = %d %s (%d)", |
241 |
SPF_debugf( "ns_initparse failed: err = %d %s (%d)", |
193 |
err, strerror( errno ), errno ); |
242 |
err, strerror( errno ), errno ); |
|
|
243 |
free(responsebuf); |
194 |
return spfrr; |
244 |
return spfrr; |
195 |
} |
245 |
} |
196 |
|
246 |
|
Lines 226-231
Link Here
|
226 |
if ( spf_dns_server->debug > 1 ) |
276 |
if ( spf_dns_server->debug > 1 ) |
227 |
SPF_debugf( "ns_parserr failed: err = %d %s (%d)", |
277 |
SPF_debugf( "ns_parserr failed: err = %d %s (%d)", |
228 |
err, strerror( errno ), errno ); |
278 |
err, strerror( errno ), errno ); |
|
|
279 |
free(responsebuf); |
229 |
return spfrr; |
280 |
return spfrr; |
230 |
} |
281 |
} |
231 |
|
282 |
|
Lines 257-264
Link Here
|
257 |
break; |
308 |
break; |
258 |
|
309 |
|
259 |
case ns_t_ns: |
310 |
case ns_t_ns: |
260 |
err = ns_name_uncompress( response, |
311 |
err = ns_name_uncompress( responsebuf, |
261 |
response + sizeof( response ), |
312 |
responsebuf + responselen, |
262 |
rdata, |
313 |
rdata, |
263 |
name_buf, sizeof( name_buf ) ); |
314 |
name_buf, sizeof( name_buf ) ); |
264 |
if ( err < 0 ) /* 0 or -1 */ |
315 |
if ( err < 0 ) /* 0 or -1 */ |
Lines 271-278
Link Here
|
271 |
break; |
322 |
break; |
272 |
|
323 |
|
273 |
case ns_t_cname: |
324 |
case ns_t_cname: |
274 |
err = ns_name_uncompress( response, |
325 |
err = ns_name_uncompress( responsebuf, |
275 |
response + sizeof( response ), |
326 |
responsebuf + responselen, |
276 |
rdata, |
327 |
rdata, |
277 |
name_buf, sizeof( name_buf ) ); |
328 |
name_buf, sizeof( name_buf ) ); |
278 |
if ( err < 0 ) /* 0 or -1 */ |
329 |
if ( err < 0 ) /* 0 or -1 */ |
Lines 286-293
Link Here
|
286 |
|
337 |
|
287 |
case ns_t_mx: |
338 |
case ns_t_mx: |
288 |
prio = ns_get16( rdata ); |
339 |
prio = ns_get16( rdata ); |
289 |
err = ns_name_uncompress( response, |
340 |
err = ns_name_uncompress( responsebuf, |
290 |
response + sizeof( response ), |
341 |
responsebuf + sizeof( responselen ), |
291 |
rdata + NS_INT16SZ, |
342 |
rdata + NS_INT16SZ, |
292 |
name_buf, sizeof( name_buf ) ); |
343 |
name_buf, sizeof( name_buf ) ); |
293 |
if ( err < 0 ) /* 0 or -1 */ |
344 |
if ( err < 0 ) /* 0 or -1 */ |
Lines 300-313
Link Here
|
300 |
break; |
351 |
break; |
301 |
|
352 |
|
302 |
case ns_t_txt: |
353 |
case ns_t_txt: |
303 |
rdata_end = rdata + rdlen; |
|
|
304 |
SPF_debugf( "TXT: (%d) \"%.*s\"", |
354 |
SPF_debugf( "TXT: (%d) \"%.*s\"", |
305 |
rdlen, rdlen-1, rdata+1 ); |
355 |
rdlen, rdlen-1, rdata+1 ); |
306 |
break; |
356 |
break; |
307 |
|
357 |
|
308 |
case ns_t_ptr: |
358 |
case ns_t_ptr: |
309 |
err = ns_name_uncompress( response, |
359 |
err = ns_name_uncompress( responsebuf, |
310 |
response + sizeof( response ), |
360 |
responsebuf + responselen, |
311 |
rdata, |
361 |
rdata, |
312 |
name_buf, sizeof( name_buf ) ); |
362 |
name_buf, sizeof( name_buf ) ); |
313 |
if ( err < 0 ) /* 0 or -1 */ |
363 |
if ( err < 0 ) /* 0 or -1 */ |
Lines 341-358
Link Here
|
341 |
{ |
391 |
{ |
342 |
case ns_t_a: |
392 |
case ns_t_a: |
343 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
393 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
344 |
sizeof( spfrr->rr[cnt]->a ) ) != SPF_E_SUCCESS ) |
394 |
sizeof(spfrr->rr[cnt]->a)) != SPF_E_SUCCESS) { |
|
|
395 |
free(responsebuf); |
345 |
return spfrr; |
396 |
return spfrr; |
346 |
memmove( &spfrr->rr[cnt]->a, rdata, sizeof( spfrr->rr[cnt]->a ) ); |
397 |
} |
|
|
398 |
memcpy(&spfrr->rr[cnt]->a, rdata, sizeof(spfrr->rr[cnt]->a)); |
347 |
cnt++; |
399 |
cnt++; |
348 |
break; |
400 |
break; |
349 |
|
401 |
|
350 |
case ns_t_aaaa: |
402 |
case ns_t_aaaa: |
351 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
403 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
352 |
sizeof( spfrr->rr[cnt]->aaaa ) ) != SPF_E_SUCCESS ) |
404 |
sizeof(spfrr->rr[cnt]->aaaa)) != SPF_E_SUCCESS) { |
|
|
405 |
free(responsebuf); |
353 |
return spfrr; |
406 |
return spfrr; |
354 |
memmove( &spfrr->rr[cnt]->aaaa, rdata, sizeof( spfrr->rr[cnt]->aaaa ) ); |
407 |
} |
355 |
|
408 |
memcpy(&spfrr->rr[cnt]->aaaa, rdata, sizeof(spfrr->rr[cnt]->aaaa)); |
356 |
cnt++; |
409 |
cnt++; |
357 |
break; |
410 |
break; |
358 |
|
411 |
|
Lines 364-371
Link Here
|
364 |
break; |
417 |
break; |
365 |
|
418 |
|
366 |
case ns_t_mx: |
419 |
case ns_t_mx: |
367 |
err = ns_name_uncompress( response, |
420 |
err = ns_name_uncompress(responsebuf, |
368 |
response + sizeof( response ), |
421 |
responsebuf + responselen, |
369 |
rdata + NS_INT16SZ, |
422 |
rdata + NS_INT16SZ, |
370 |
name_buf, sizeof( name_buf ) ); |
423 |
name_buf, sizeof( name_buf ) ); |
371 |
if ( err < 0 ) /* 0 or -1 */ |
424 |
if ( err < 0 ) /* 0 or -1 */ |
Lines 373-384
Link Here
|
373 |
if ( spf_dns_server->debug > 1 ) |
426 |
if ( spf_dns_server->debug > 1 ) |
374 |
SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
427 |
SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
375 |
err, strerror( errno ), errno ); |
428 |
err, strerror( errno ), errno ); |
|
|
429 |
free(responsebuf); |
376 |
return spfrr; |
430 |
return spfrr; |
377 |
} |
431 |
} |
378 |
|
432 |
|
379 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
433 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
380 |
strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) |
434 |
strlen(name_buf) + 1 ) != SPF_E_SUCCESS) { |
|
|
435 |
free(responsebuf); |
381 |
return spfrr; |
436 |
return spfrr; |
|
|
437 |
} |
382 |
strcpy( spfrr->rr[cnt]->mx, name_buf ); |
438 |
strcpy( spfrr->rr[cnt]->mx, name_buf ); |
383 |
|
439 |
|
384 |
cnt++; |
440 |
cnt++; |
Lines 390-397
Link Here
|
390 |
u_char *src, *dst; |
446 |
u_char *src, *dst; |
391 |
size_t len; |
447 |
size_t len; |
392 |
|
448 |
|
393 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, rdlen ) != SPF_E_SUCCESS ) |
449 |
/* Just rdlen is enough because there is at least one |
|
|
450 |
* length byte. */ |
451 |
if (SPF_dns_rr_buf_realloc(spfrr, cnt, rdlen) != SPF_E_SUCCESS) { |
452 |
free(responsebuf); |
394 |
return spfrr; |
453 |
return spfrr; |
|
|
454 |
} |
395 |
|
455 |
|
396 |
dst = (u_char *)(spfrr->rr[cnt]->txt); |
456 |
dst = (u_char *)(spfrr->rr[cnt]->txt); |
397 |
len = 0; |
457 |
len = 0; |
Lines 400-414
Link Here
|
400 |
{ |
460 |
{ |
401 |
len = *src; |
461 |
len = *src; |
402 |
src++; |
462 |
src++; |
|
|
463 |
rdlen--; |
464 |
|
465 |
/* Avoid buffer overrun if len is junk. */ |
466 |
if (len > rdlen) |
467 |
len = rdlen; |
403 |
memcpy( dst, src, len ); |
468 |
memcpy( dst, src, len ); |
404 |
dst += len; |
469 |
dst += len; |
405 |
src += len; |
470 |
src += len; |
406 |
rdlen -= len + 1; |
471 |
rdlen -= len; |
407 |
} |
472 |
} |
408 |
*dst = '\0'; |
473 |
*dst = '\0'; |
409 |
} else { |
474 |
} else { |
410 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, 1 ) != SPF_E_SUCCESS ) |
475 |
if (SPF_dns_rr_buf_realloc(spfrr, cnt, 1) != SPF_E_SUCCESS) { |
|
|
476 |
free(responsebuf); |
411 |
return spfrr; |
477 |
return spfrr; |
|
|
478 |
} |
412 |
spfrr->rr[cnt]->txt[0] = '\0'; |
479 |
spfrr->rr[cnt]->txt[0] = '\0'; |
413 |
} |
480 |
} |
414 |
|
481 |
|
Lines 416-423
Link Here
|
416 |
break; |
483 |
break; |
417 |
|
484 |
|
418 |
case ns_t_ptr: |
485 |
case ns_t_ptr: |
419 |
err = ns_name_uncompress( response, |
486 |
err = ns_name_uncompress(responsebuf, |
420 |
response + sizeof( response ), |
487 |
responsebuf + responselen, |
421 |
rdata, |
488 |
rdata, |
422 |
name_buf, sizeof( name_buf ) ); |
489 |
name_buf, sizeof( name_buf ) ); |
423 |
if ( err < 0 ) /* 0 or -1 */ |
490 |
if ( err < 0 ) /* 0 or -1 */ |
Lines 425-436
Link Here
|
425 |
if ( spf_dns_server->debug > 1 ) |
492 |
if ( spf_dns_server->debug > 1 ) |
426 |
SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
493 |
SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
427 |
err, strerror( errno ), errno ); |
494 |
err, strerror( errno ), errno ); |
|
|
495 |
free(responsebuf); |
428 |
return spfrr; |
496 |
return spfrr; |
429 |
} |
497 |
} |
430 |
|
498 |
|
431 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
499 |
if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
432 |
strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) |
500 |
strlen(name_buf) + 1) != SPF_E_SUCCESS) { |
|
|
501 |
free(responsebuf); |
433 |
return spfrr; |
502 |
return spfrr; |
|
|
503 |
} |
434 |
strcpy( spfrr->rr[cnt]->ptr, name_buf ); |
504 |
strcpy( spfrr->rr[cnt]->ptr, name_buf ); |
435 |
|
505 |
|
436 |
cnt++; |
506 |
cnt++; |
Lines 447-452
Link Here
|
447 |
if ( spfrr->num_rr == 0 ) |
517 |
if ( spfrr->num_rr == 0 ) |
448 |
spfrr->herrno = NO_DATA; |
518 |
spfrr->herrno = NO_DATA; |
449 |
|
519 |
|
|
|
520 |
free(responsebuf); |
450 |
return spfrr; |
521 |
return spfrr; |
451 |
} |
522 |
} |
452 |
|
523 |
|