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