From e1a3f32f604bcdf65ac20d04ddd2bc93bc9f4deb Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 18 May 2015 15:18:53 +0100 Subject: [PATCH] Fix truncated dns-lookup return record handling --- src/src/dns.c | 25 +++++++++++++++---------- src/src/host.c | 18 ++++++++---------- src/src/lookups/dnsdb.c | 2 +- src/src/verify.c | 4 ++-- test/scripts/0000-Basic/0002 | 6 ++++++ test/stderr/0020 | 1 - test/stdout/0002 | 6 ++++++ 7 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/src/dns.c b/src/src/dns.c index 51029d4a5..ad98a9d4e 100644 --- a/src/src/dns.c +++ b/src/src/dns.c @@ -1086,31 +1086,36 @@ Argument: dnsa the DNS answer block rr the RR -Returns: pointer to a chain of dns_address items +Returns: pointer to a chain of dns_address items; NULL when the dnsa was overrun */ dns_address * dns_address_from_rr(dns_answer *dnsa, dns_record *rr) { -dns_address *yield = NULL; - -dnsa = dnsa; /* Stop picky compilers warning */ +dns_address * yield = NULL; +uschar * dnsa_lim = dnsa->answer + dnsa->answerlen; if (rr->type == T_A) { uschar *p = US rr->data; - yield = store_get(sizeof(dns_address) + 20); - (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - yield->next = NULL; + if (p + 4 <= dnsa_lim) + { + yield = store_get(sizeof(dns_address) + 20); + (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + yield->next = NULL; + } } #if HAVE_IPV6 else { - yield = store_get(sizeof(dns_address) + 50); - inet_ntop(AF_INET6, US rr->data, CS yield->address, 50); - yield->next = NULL; + if (rr->data + 16 <= dnsa_lim) + { + yield = store_get(sizeof(dns_address) + 50); + inet_ntop(AF_INET6, US rr->data, CS yield->address, 50); + yield->next = NULL; + } } #endif /* HAVE_IPV6 */ diff --git a/src/src/host.c b/src/src/host.c index d65da7578..9c63cb95a 100644 --- a/src/src/host.c +++ b/src/src/host.c @@ -251,11 +251,10 @@ else } for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; + rr; rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) - { - if (rr->type == type) count++; - } + if (rr->type == type) + count++; yield = store_get(sizeof(struct hostent)); alist = store_get((count + 1) * sizeof(char **)); @@ -268,14 +267,14 @@ else yield->h_addr_list = CSS alist; for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; + rr; rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) { int i, n; int x[4]; dns_address *da; if (rr->type != type) continue; - da = dns_address_from_rr(&dnsa, rr); + if (!(da = dns_address_from_rr(&dnsa, rr))) break; *alist++ = adds; n = host_aton(da->address, x); for (i = 0; i < n; i++) @@ -2356,7 +2355,7 @@ for (; i >= 0; i--) fully_qualified_name = NULL; for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; + rr; rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) { if (rr->type == type) @@ -2368,15 +2367,14 @@ for (; i >= 0; i--) DEBUG(D_host_lookup) { - if (da == NULL) - debug_printf("no addresses extracted from A6 RR for %s\n", + if (!da) debug_printf("no addresses extracted from A6 RR for %s\n", host->name); } /* This loop runs only once for A and AAAA records, but may run several times for an A6 record that generated multiple addresses. */ - for (; da != NULL; da = da->next) + for (; da; da = da->next) { #ifndef STAND_ALONE if (ignore_target_hosts != NULL && diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c index 2e6805dc9..bfb0c283f 100644 --- a/src/src/lookups/dnsdb.c +++ b/src/src/lookups/dnsdb.c @@ -391,7 +391,7 @@ while ((domain = string_nextinlist(&keystring, &sep, NULL, 0))) if (type == T_A || type == T_AAAA || type == T_ADDRESSES) { dns_address *da; - for (da = dns_address_from_rr(&dnsa, rr); da != NULL; da = da->next) + for (da = dns_address_from_rr(&dnsa, rr); da; da = da->next) { if (ptr != 0) yield = string_cat(yield, &size, &ptr, outsep, 1); yield = string_cat(yield, &size, &ptr, da->address, diff --git a/src/src/verify.c b/src/src/verify.c index 93ab9112d..3c2942733 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -3620,13 +3620,13 @@ if (t == NULL) dns_record *rr; dns_address **addrp = &(cb->rhs); for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; + rr; rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) { if (rr->type == T_A) { dns_address *da = dns_address_from_rr(&dnsa, rr); - if (da != NULL) + if (da) { *addrp = da; while (da->next != NULL) da = da->next; diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002 index 328f5a3ca..acb308324 100644 --- a/test/scripts/0000-Basic/0002 +++ b/test/scripts/0000-Basic/0002 @@ -842,6 +842,7 @@ match_address: ${if match_address{a.b.c}{a.b.c}{yes}{no}} **** # Sender host name and address etc, all unset exim -be +-be Sender host name and address etc, all unset -oMa sender_host_address = $sender_host_address sender_host_port = $sender_host_port -oMaa sender_host_authenticated = $sender_host_authenticated @@ -855,6 +856,7 @@ exim -be **** # Sender host name and address etc, all set except host name. exim -d-all+expand -be -oMa V4NET.0.0.1.1234 -oMaa AAA -oMai philip -oMas xx@yy.zz -oMi 1.1.1.1.99 -oMr special -oMt me +-be Sender host name and address etc, all set except host name. -oMa sender_host_address = $sender_host_address sender_host_port = $sender_host_port -oMaa sender_host_authenticated = $sender_host_authenticated @@ -867,17 +869,20 @@ exim -d-all+expand -be -oMa V4NET.0.0.1.1234 -oMaa AAA -oMai philip -oMas xx@yy. **** # Sender host name explicitly set exim -be -oMa V4NET.0.0.1.1234 -oMs my.host.name +-be Sender host name explicitly set -oMa sender_host_address = $sender_host_address sender_host_port = $sender_host_port -oMs sender_host_name = $sender_host_name **** # Sender host name lookup fails (V4NET.11.12.13 is not reverse registered) exim -be -oMa V4NET.11.12.13 +be Sender host name lookup fails (V4NET.11.12.13 is not reverse registered) -oMs sender_host_name = $sender_host_name host_lookup_failed = $host_lookup_failed **** # Sender host name and protocol set by Sendmail-compatible option exim -be -pspecial:host.name +-be Sender host name and protocol set by Sendmail-compatible option -p received_protocol = $received_protocol -p sender_host_name = $sender_host_name **** @@ -886,6 +891,7 @@ exim -be -pspecial:host.name # we are skipping. The debug output for this test will show when # the lookup occurs. exim -d-all+host_lookup+expand -be -oMa V4NET.0.0.1.1234 -oMaa AAA -oMai philip -oMas xx@yy.zz -oMi 1.1.1.1.99 -oMr special -oMt me +-be Sender host name and address etc, all set except host name -oMa sender_host_address = $sender_host_address sender_host_port = $sender_host_port -oMaa sender_host_authenticated = $sender_host_authenticated diff --git a/test/stderr/0020 b/test/stderr/0020 index b5961e204..ee9c757d8 100644 --- a/test/stderr/0020 +++ b/test/stderr/0020 @@ -67,7 +67,6 @@ MUNGED: ::1 will be omitted in what follows >>> name=manyhome.test.ex address=10.250.104.60 >>> name=manyhome.test.ex address=10.250.104.61 >>> name=manyhome.test.ex address=10.250.104.62 ->>> name=manyhome.test.ex address=0.0.0.0 >>> checking addresses for manyhome.test.ex >>> 10.250.104.0 >>> 10.250.104.1 diff --git a/test/stdout/0002 b/test/stdout/0002 index 6c195b269..d145e7ec3 100644 --- a/test/stdout/0002 +++ b/test/stdout/0002 @@ -787,6 +787,7 @@ xyz > yes > match_address: no > +> -be Sender host name and address etc, all unset > -oMa sender_host_address = > sender_host_port = 0 > -oMaa sender_host_authenticated = @@ -798,6 +799,7 @@ xyz > -oMs sender_host_name = > -oMt sender_ident = CALLER > +> -be Sender host name and address etc, all set except host name. > -oMa sender_host_address = V4NET.0.0.1 > sender_host_port = 1234 > -oMaa sender_host_authenticated = AAA @@ -808,16 +810,20 @@ xyz > -oMr received_protocol = special > -oMt sender_ident = me > +> -be Sender host name explicitly set > -oMa sender_host_address = V4NET.0.0.1 > sender_host_port = 1234 > -oMs sender_host_name = my.host.name > +> be Sender host name lookup fails (V4NET.11.12.13 is not reverse registered) > -oMs sender_host_name = > host_lookup_failed = 1 > +> -be Sender host name and protocol set by Sendmail-compatible option > -p received_protocol = special > -p sender_host_name = host.name > +> -be Sender host name and address etc, all set except host name > -oMa sender_host_address = V4NET.0.0.1 > sender_host_port = 1234 > -oMaa sender_host_authenticated = AAA -- 2.30.2