Mercurial > dnsbl
comparison src/dnsbl.cpp @ 414:d5a1ed33d3ae
spf code now handles mx,exists,ptr tags, multiple A records, %{i} macro
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 25 Apr 2017 14:48:19 -0700 |
parents | 6b03435868cb |
children | 16451edcb962 |
comparison
equal
deleted
inserted
replaced
413:54809ee70bb8 | 414:d5a1ed33d3ae |
---|---|
295 | 295 |
296 //////////////////////////////////////////////// | 296 //////////////////////////////////////////////// |
297 // Ask a dns question and get an A record answer in network byte order. | 297 // Ask a dns question and get an A record answer in network byte order. |
298 // We don't try very hard, just using the default resolver retry settings. | 298 // We don't try very hard, just using the default resolver retry settings. |
299 // If we cannot get an answer, we just accept the mail. | 299 // If we cannot get an answer, we just accept the mail. |
300 // If the qtype is ns_t_txt, the answer is placed in txt_answer which | 300 // If the qtype is ns_t_txt, the answer is placed in my_answer which |
301 // must be non-null, and the return value can be ignored. | 301 // must be non-null, and the return value can be ignored. |
302 // A null string is returned in txt_answer in the case of errors. | 302 // A null string is returned in my_answer in the case of errors. |
303 // If the qtype is ns_t_a, the ip address is returned in network byte order. | 303 // If the qtype is ns_t_a, one of the ip addresses is returned in network byte order, |
304 // and if my_answer is non-null, all the ip addresses are returned in | |
305 // my_answer (in network byte order), prepended with the count. | |
304 // IP address 0 is returned in case of errors. | 306 // IP address 0 is returned in case of errors. |
305 // | 307 // |
306 uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *txt_answer, size_t txt_size) { | 308 uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *my_answer, size_t my_size) { |
307 if (txt_answer) txt_answer[0] = '\0'; // return null string if there are no txt answers | 309 if (my_answer) my_answer[0] = '\0'; // return null string if there are no txt answers |
308 | 310 |
309 // tell sendmail we are still working | 311 // tell sendmail we are still working |
310 #if _FFR_SMFI_PROGRESS | 312 #if _FFR_SMFI_PROGRESS |
311 if (priv.eom) smfi_progress(priv.ctx); | 313 if (priv.eom) smfi_progress(priv.ctx); |
312 #endif | 314 #endif |
410 } | 412 } |
411 } | 413 } |
412 } | 414 } |
413 int rrnum = 0; | 415 int rrnum = 0; |
414 if (qtype == ns_t_a) { | 416 if (qtype == ns_t_a) { |
417 uint32_t *ans = (uint32_t *)my_answer; | |
418 size_t c = 0; | |
419 size_t m = my_size/4; // 1 + max ipv4 addresses that will fit in the answer buffer | |
415 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { | 420 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { |
416 if (ns_rr_type(rr) == qtype) { | 421 if (ns_rr_type(rr) == qtype) { |
417 uint32_t address; | 422 uint32_t address; |
418 memcpy(&address, ns_rr_rdata(rr), sizeof(address)); | 423 memcpy(&address, ns_rr_rdata(rr), sizeof(address)); |
419 ret_address = address; | 424 ret_address = address; |
425 if (ans && (c < m-1)) { | |
426 c++; | |
427 ans[c] = address; | |
428 } | |
420 } | 429 } |
421 } | 430 } |
422 } | 431 if (ans && (c < m)) ans[0] = c; |
423 if ((qtype == ns_t_txt) && (txt_answer) && (txt_size > 7)) { | 432 } |
424 txt_answer[0] = '\0'; // return null string if there are no txt answers | 433 if ((qtype == ns_t_mx) && (my_answer) && (my_size > 1)) { |
425 txt_size--; // allow room for terminating null; | 434 uint32_t c = 0; |
435 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { | |
436 if (ns_rr_type(rr) == qtype) { | |
437 char exchange[NS_MAXDNAME]; | |
438 size_t rdlen = ns_rr_rdlen(rr); | |
439 const unsigned char *rdata = ns_rr_rdata(rr); | |
440 const uint16_t pri = ns_get16(rdata); | |
441 int len = dn_expand(glom.answer, glom.answer+glom.length, rdata + 2, exchange, sizeof(exchange)); | |
442 if ((len > 0) && (my_size > len+2)) { | |
443 strcpy(my_answer, exchange); | |
444 my_answer += len + 1; | |
445 my_size -= len + 1; | |
446 c++; | |
447 } | |
448 } | |
449 } | |
450 *my_answer = '\0'; // final trailing null | |
451 ret_address = htonl(c); | |
452 } | |
453 if ((qtype == ns_t_txt) && (my_answer) && (my_size > 7)) { | |
454 my_answer[0] = '\0'; // return null string if there are no txt answers | |
455 my_size--; // allow room for terminating null; | |
426 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { | 456 while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { |
427 if (ns_rr_type(rr) == qtype) { | 457 if (ns_rr_type(rr) == qtype) { |
428 size_t offset = 0; | 458 size_t offset = 0; |
429 size_t rdlen = ns_rr_rdlen(rr); | 459 size_t rdlen = ns_rr_rdlen(rr); |
430 const unsigned char *rdata = ns_rr_rdata(rr); | 460 const unsigned char *rdata = ns_rr_rdata(rr); |
431 #ifdef RESOLVER_DEBUG | 461 #ifdef RESOLVER_DEBUG |
432 char text[1000]; | 462 char text[1000]; |
433 snprintf(text, sizeof(text), "found txt record rdlen = %d", rdlen); | 463 snprintf(text, sizeof(text), "found txt record rdlen = %d", rdlen); |
434 my_syslog(text); | 464 my_syslog(text); |
435 #endif | 465 #endif |
436 while ((offset < txt_size) && rdlen) { | 466 while ((offset < my_size) && rdlen) { |
437 size_t slen = size_t(*(rdata++)); | 467 size_t slen = size_t(*(rdata++)); |
438 rdlen--; | 468 rdlen--; |
439 size_t m = min(slen, rdlen); | 469 size_t m = min(slen, rdlen); |
440 m = min(m, txt_size-offset); | 470 m = min(m, my_size-offset); |
441 memcpy(txt_answer+offset, rdata, m); | 471 memcpy(my_answer+offset, rdata, m); |
442 offset += m; | 472 offset += m; |
443 rdata += m; | 473 rdata += m; |
444 rdlen -= m; | 474 rdlen -= m; |
445 } | 475 } |
446 txt_answer[offset] = '\0'; // trailing null | 476 my_answer[offset] = '\0'; // trailing null |
447 #ifdef RESOLVER_DEBUG | 477 #ifdef RESOLVER_DEBUG |
448 snprintf(text, sizeof(text), "found txt record %s", txt_answer); | 478 snprintf(text, sizeof(text), "found txt record %s", my_answer); |
449 my_syslog(text); | 479 my_syslog(text); |
450 #endif | 480 #endif |
451 if (strncasecmp(txt_answer, "v=spf1 ", 7) == 0) break; | 481 if (strncasecmp(my_answer, "v=spf1 ", 7) == 0) break; |
452 } | 482 } |
453 } | 483 } |
454 if (strncasecmp(txt_answer, "v=spf1 ", 7) != 0) { | 484 if (strncasecmp(my_answer, "v=spf1 ", 7) != 0) { |
455 txt_answer[0] = '\0'; // return null string if there are no spf1 txt answers | 485 my_answer[0] = '\0'; // return null string if there are no spf1 txt answers |
456 } | 486 } |
457 } | 487 } |
458 } | 488 } |
459 pthread_mutex_unlock(&resolve_mutex); | 489 pthread_mutex_unlock(&resolve_mutex); |
460 #ifdef RESOLVER_DEBUG | 490 #ifdef RESOLVER_DEBUG |