Skip to content

Commit

Permalink
Change host_lookup re-forward from byname to bydns; checking DNSSEC
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Harris committed May 19, 2015
1 parent 7cd171b commit 1f155f8
Show file tree
Hide file tree
Showing 24 changed files with 67 additions and 220 deletions.
6 changes: 2 additions & 4 deletions doc/doc-docbook/spec.xfpt
Original file line number Diff line number Diff line change
Expand Up @@ -12223,7 +12223,8 @@ received. It is empty if there was no successful authentication. See also
If an attempt to populate &$sender_host_name$& has been made
(by reference, &%hosts_lookup%& or
otherwise) then this boolean will have been set true if, and only if, the
resolver library states that the reverse DNS was authenticated data. At all
resolver library states that both
the reverse and forward DNS were authenticated data. At all
other times, this variable is false.

It is likely that you will need to coerce DNSSEC support on in the resolver
Expand All @@ -12235,9 +12236,6 @@ dns_dnssec_ok = 1
Exim does not perform DNSSEC validation itself, instead leaving that to a
validating resolver (eg, unbound, or bind with suitable configuration).

Exim does not (currently) check to see if the forward DNS was also secured
with DNSSEC, only the reverse DNS.

If you have changed &%host_lookup_order%& so that &`bydns`& is not the first
mechanism in the list, then this variable will be false.

Expand Down
3 changes: 3 additions & 0 deletions doc/doc-txt/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ JH/28 Bug 1588: Do not use the A lookup following an AAAA for setting the FQDN.

JH/29 Bug 1632: Removed the word "rejected" from line logged for ACL discards.

JH/30 Check the forward DNS lookup for DNSSEC, in addition to the reverse,
when evaluating $sender_host_dnssec.


Exim version 4.85
-----------------
Expand Down
3 changes: 2 additions & 1 deletion src/src/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ extern void host_build_hostlist(host_item **, const uschar *, BOOL);
extern ip_address_item *host_build_ifacelist(const uschar *, uschar *);
extern void host_build_log_info(void);
extern void host_build_sender_fullhost(void);
extern BOOL host_find_byname(host_item *, const uschar *, int, const uschar **, BOOL);
extern BOOL host_find_byname(host_item *, const uschar *, int,
const uschar **, BOOL);
extern int host_find_bydns(host_item *, const uschar *, int, uschar *, uschar *,
uschar *, const dnssec_domains *, const uschar **, BOOL *);
extern ip_address_item *host_find_interfaces(void);
Expand Down
39 changes: 20 additions & 19 deletions src/src/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1639,8 +1639,7 @@ if (running_in_test_harness &&
/* Do lookups directly in the DNS or via gethostbyaddr() (or equivalent), in
the order specified by the host_lookup_order option. */

while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
!= NULL)
while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
{
if (strcmpic(ordername, US"bydns") == 0)
{
Expand All @@ -1661,8 +1660,6 @@ while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
int count = 0;
int old_pool = store_pool;

/* Ideally we'd check DNSSEC both forward and reverse, but we use the
gethost* routines for forward, so can't do that unless/until we rewrite. */
sender_host_dnssec = dns_is_secure(&dnsa);
DEBUG(D_dns)
debug_printf("Reverse DNS security status: %s\n",
Expand Down Expand Up @@ -1710,8 +1707,8 @@ while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
"empty name: treated as non-existent host name\n");
continue;
}
if (sender_host_name == NULL) sender_host_name = s;
else *aptr++ = s;
if (!sender_host_name) sender_host_name = s;
else *aptr++ = s;
while (*s != 0) { *s = tolower(*s); s++; }
}

Expand Down Expand Up @@ -1790,32 +1787,39 @@ for (hname = sender_host_name; hname != NULL; hname = *aliases++)
int rc;
BOOL ok = FALSE;
host_item h;
dnssec_domains d;

h.next = NULL;
h.name = hname;
h.mx = MX_NONE;
h.address = NULL;
d.request = sender_host_dnssec ? US"*" : NULL;;
d.require = NULL;

/* When called with the last argument FALSE, host_find_byname() won't return
HOST_FOUND_LOCAL. If the incoming address is an IPv4 address expressed in
IPv6 format, we must compare the IPv4 part to any IPv4 addresses. */

if ((rc = host_find_byname(&h, NULL, 0, NULL, FALSE)) == HOST_FOUND)
if ( (rc = host_find_bydns(&h, NULL, HOST_FIND_BY_A,
NULL, NULL, NULL, &d, NULL, NULL)) == HOST_FOUND
|| rc == HOST_FOUND_LOCAL
)
{
host_item *hh;
HDEBUG(D_host_lookup) debug_printf("checking addresses for %s\n", hname);

/* If the forward lookup was not secure we cancel the is-secure variable */

DEBUG(D_dns) debug_printf("Forward DNS security status: %s\n",
h.dnssec == DS_YES ? "DNSSEC verified (AD)" : "unverified");
if (h.dnssec != DS_YES) sender_host_dnssec = FALSE;

for (hh = &h; hh != NULL; hh = hh->next)
{
if (host_is_in_net(hh->address, sender_host_address, 0))
{
HDEBUG(D_host_lookup) debug_printf(" %s OK\n", hh->address);
ok = TRUE;
break;
}
else
{
HDEBUG(D_host_lookup) debug_printf(" %s\n", hh->address);
}
}

if (!ok) HDEBUG(D_host_lookup)
debug_printf("no IP address for %s matched %s\n", hname,
sender_host_address);
Expand All @@ -1828,9 +1832,7 @@ for (hname = sender_host_name; hname != NULL; hname = *aliases++)
return DEFER;
}
else
{
HDEBUG(D_host_lookup) debug_printf("no IP addresses found for %s\n", hname);
}

/* If this name is no good, and it's the sender name, set it null pro tem;
if it's an alias, just remove it from the list. */
Expand Down Expand Up @@ -2539,8 +2541,7 @@ that gets set for DNS syntax check errors. */
if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
(whichrrs & HOST_FIND_SEARCH_PARENTS) != 0,
dnssec_request
);
dnssec_request);
host_find_failed_syntax = FALSE;

/* First, if requested, look for SRV records. The service name is given; we
Expand Down
4 changes: 2 additions & 2 deletions src/src/ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ else if (string_is_ip_address(hostname, NULL) != 0)
else
{
shost.name = string_copy(hostname);
if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL,
FALSE) != HOST_FOUND)
if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE,
NULL, FALSE) != HOST_FOUND)
{
*errstr = string_sprintf("no IP address found for host %s", shost.name);
return -1;
Expand Down
1 change: 1 addition & 0 deletions src/src/routers/iplookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ while ((hostname = string_nextinlist(&listptr, &sep, host_buffer,
host->address = host->name;
else
{
/*XXX might want dnssec request/require on an iplookup router? */
int rc = host_find_byname(host, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, TRUE);
if (rc == HOST_FIND_FAILED || rc == HOST_FIND_AGAIN) continue;
}
Expand Down
4 changes: 4 additions & 0 deletions src/src/smtp_in.c
Original file line number Diff line number Diff line change
Expand Up @@ -3009,6 +3009,7 @@ else

if (helo_verified)
{
/*XXX have sender_host_dnssec */
HDEBUG(D_receive) debug_printf("matched host name\n");
}
else
Expand All @@ -3018,6 +3019,7 @@ else
{
helo_verified = strcmpic(*aliases++, sender_helo_name) == 0;
if (helo_verified) break;
/*XXX have sender_host_dnssec */
}
HDEBUG(D_receive)
{
Expand All @@ -3039,6 +3041,8 @@ else
h.next = NULL;
HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
sender_helo_name);
/*XXX would like to determine dnssec status here */
/* need to change to bydns */
rc = host_find_byname(&h, NULL, 0, NULL, TRUE);
if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
{
Expand Down
4 changes: 4 additions & 0 deletions src/src/verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -3245,6 +3245,10 @@ if (*t == 0)
h.address = NULL;
h.mx = MX_NONE;

/* Using byname rather than bydns here means we cannot determine dnssec
status. On the other hand it is unclear how that could be either
propagated up or enforced. */

rc = host_find_byname(&h, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, FALSE);
if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
{
Expand Down
11 changes: 3 additions & 8 deletions test/stderr/0002
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,7 @@ expanding: ----> No lookup yet: ${if eq{black}{white}{$sender_host_name}{No}}
result: ----> No lookup yet: No
looking up host name for V4NET.0.0.1
IP address lookup yielded "ten-1.test.ex"
using host_fake_gethostbyname for ten-1.test.ex (IPv4)
MUNGED: ::1 will be omitted in what follows
get[host|ipnode]byname[2] looked up these IP addresses:
name=ten-1.test.ex address=V4NET.0.0.1
ten-1.test.ex V4NET.0.0.1 mx=-1 sort=xx
checking addresses for ten-1.test.ex
V4NET.0.0.1 OK
sender_fullhost = ten-1.test.ex [V4NET.0.0.1]
Expand Down Expand Up @@ -160,13 +157,11 @@ looking up host name for V4NET.0.0.1
DNS lookup of 1.0.0.V4NET.in-addr.arpa (PTR) using fakens
DNS lookup of 1.0.0.V4NET.in-addr.arpa (PTR) succeeded
IP address lookup yielded "ten-1.test.ex"
using host_fake_gethostbyname for ten-1.test.ex (IPv4)
DNS lookup of ten-1.test.ex (A) using fakens
DNS lookup of ten-1.test.ex (A) succeeded
MUNGED: ::1 will be omitted in what follows
get[host|ipnode]byname[2] looked up these IP addresses:
name=ten-1.test.ex address=V4NET.0.0.1
ten-1.test.ex V4NET.0.0.1 mx=-1 sort=xx
checking addresses for ten-1.test.ex
Forward DNS security status: unverified
V4NET.0.0.1 OK
sender_fullhost = ten-1.test.ex [V4NET.0.0.1]
sender_rcvhost = ten-1.test.ex ([V4NET.0.0.1])
Expand Down
113 changes: 13 additions & 100 deletions test/stderr/0020
Original file line number Diff line number Diff line change
Expand Up @@ -2,114 +2,27 @@
>>> host in host_lookup? yes (matched "10.250.104.0/21")
>>> looking up host name for 10.250.104.42
>>> IP address lookup yielded "manyhome.test.ex"
MUNGED: ::1 will be omitted in what follows
>>> get[host|ipnode]byname[2] looked up these IP addresses:
>>> name=manyhome.test.ex address=10.250.104.0
>>> name=manyhome.test.ex address=10.250.104.1
>>> name=manyhome.test.ex address=10.250.104.2
>>> name=manyhome.test.ex address=10.250.104.3
>>> name=manyhome.test.ex address=10.250.104.4
>>> name=manyhome.test.ex address=10.250.104.5
>>> name=manyhome.test.ex address=10.250.104.6
>>> name=manyhome.test.ex address=10.250.104.7
>>> name=manyhome.test.ex address=10.250.104.8
>>> name=manyhome.test.ex address=10.250.104.9
>>> name=manyhome.test.ex address=10.250.104.10
>>> name=manyhome.test.ex address=10.250.104.11
>>> name=manyhome.test.ex address=10.250.104.12
>>> name=manyhome.test.ex address=10.250.104.13
>>> name=manyhome.test.ex address=10.250.104.14
>>> name=manyhome.test.ex address=10.250.104.15
>>> name=manyhome.test.ex address=10.250.104.16
>>> name=manyhome.test.ex address=10.250.104.17
>>> name=manyhome.test.ex address=10.250.104.18
>>> name=manyhome.test.ex address=10.250.104.19
>>> name=manyhome.test.ex address=10.250.104.20
>>> name=manyhome.test.ex address=10.250.104.21
>>> name=manyhome.test.ex address=10.250.104.22
>>> name=manyhome.test.ex address=10.250.104.23
>>> name=manyhome.test.ex address=10.250.104.24
>>> name=manyhome.test.ex address=10.250.104.25
>>> name=manyhome.test.ex address=10.250.104.26
>>> name=manyhome.test.ex address=10.250.104.27
>>> name=manyhome.test.ex address=10.250.104.28
>>> name=manyhome.test.ex address=10.250.104.29
>>> name=manyhome.test.ex address=10.250.104.30
>>> name=manyhome.test.ex address=10.250.104.31
>>> name=manyhome.test.ex address=10.250.104.32
>>> name=manyhome.test.ex address=10.250.104.33
>>> name=manyhome.test.ex address=10.250.104.34
>>> name=manyhome.test.ex address=10.250.104.35
>>> name=manyhome.test.ex address=10.250.104.36
>>> name=manyhome.test.ex address=10.250.104.37
>>> name=manyhome.test.ex address=10.250.104.38
>>> name=manyhome.test.ex address=10.250.104.39
>>> name=manyhome.test.ex address=10.250.104.40
>>> name=manyhome.test.ex address=10.250.104.41
>>> name=manyhome.test.ex address=10.250.104.42
>>> name=manyhome.test.ex address=10.250.104.43
>>> name=manyhome.test.ex address=10.250.104.44
>>> name=manyhome.test.ex address=10.250.104.45
>>> name=manyhome.test.ex address=10.250.104.46
>>> name=manyhome.test.ex address=10.250.104.47
>>> name=manyhome.test.ex address=10.250.104.48
>>> name=manyhome.test.ex address=10.250.104.49
>>> name=manyhome.test.ex address=10.250.104.50
>>> name=manyhome.test.ex address=10.250.104.51
>>> name=manyhome.test.ex address=10.250.104.52
>>> name=manyhome.test.ex address=10.250.104.53
>>> name=manyhome.test.ex address=10.250.104.54
>>> name=manyhome.test.ex address=10.250.104.55
>>> name=manyhome.test.ex address=10.250.104.56
>>> name=manyhome.test.ex address=10.250.104.57
>>> name=manyhome.test.ex address=10.250.104.58
>>> name=manyhome.test.ex address=10.250.104.59
>>> 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
>>> checking addresses for manyhome.test.ex
>>> 10.250.104.0
>>> 10.250.104.1
>>> 10.250.104.51
>>> 10.250.104.17
>>> 10.250.104.2
>>> 10.250.104.3
>>> 10.250.104.4
>>> 10.250.104.5
>>> 10.250.104.6
>>> 10.250.104.7
>>> 10.250.104.26
>>> 10.250.104.8
>>> 10.250.104.9
>>> 10.250.104.10
>>> 10.250.104.11
>>> 10.250.104.12
>>> 10.250.104.13
>>> 10.250.104.14
>>> 10.250.104.15
>>> 10.250.104.16
>>> 10.250.104.17
>>> 10.250.104.18
>>> 10.250.104.19
>>> 10.250.104.20
>>> 10.250.104.25
>>> 10.250.104.21
>>> 10.250.104.22
>>> 10.250.104.39
>>> 10.250.104.32
>>> 10.250.104.29
>>> 10.250.104.23
>>> 10.250.104.24
>>> 10.250.104.25
>>> 10.250.104.26
>>> 10.250.104.27
>>> 10.250.104.43
>>> 10.250.104.46
>>> 10.250.104.28
>>> 10.250.104.29
>>> 10.250.104.30
>>> 10.250.104.31
>>> 10.250.104.32
>>> 10.250.104.33
>>> 10.250.104.34
>>> 10.250.104.35
>>> 10.250.104.36
>>> 10.250.104.37
>>> 10.250.104.38
>>> 10.250.104.39
>>> 10.250.104.40
>>> 10.250.104.4
>>> 10.250.104.41
>>> 10.250.104.15
>>> 10.250.104.14
>>> 10.250.104.45
>>> 10.250.104.42 OK
>>> host in host_reject_connection? no (option unset)
>>> host in sender_unqualified_hosts? no (option unset)
Expand Down
8 changes: 2 additions & 6 deletions test/stderr/0023
Original file line number Diff line number Diff line change
Expand Up @@ -1089,14 +1089,8 @@ LOG: H=[28.28.28.28] F=<a@baddomain> rejected RCPT <x@y>
>>> looking up host name for V4NET.0.0.3
>>> IP address lookup yielded "ten-3.test.ex"
>>> alias "ten-3-alias.test.ex"
MUNGED: ::1 will be omitted in what follows
>>> get[host|ipnode]byname[2] looked up these IP addresses:
>>> name=ten-3.test.ex address=V4NET.0.0.3
>>> checking addresses for ten-3.test.ex
>>> V4NET.0.0.3 OK
MUNGED: ::1 will be omitted in what follows
>>> get[host|ipnode]byname[2] looked up these IP addresses:
>>> name=ten-3-alias.test.ex address=V4NET.0.0.3
>>> checking addresses for ten-3-alias.test.ex
>>> V4NET.0.0.3 OK
>>> require: condition test succeeded in ACL "acl_V4NET_0_0"
Expand Down Expand Up @@ -1139,6 +1133,7 @@ LOG: H=[V4NET.0.0.97] F=<> rejected RCPT <x@y>: host lookup failed for reverse l
>>> looking up host name for V4NET.99.99.96
>>> IP address lookup yielded "x.test.again.dns"
>>> x.test.again.dns in dns_again_means_nonexist? no (option unset)
>>> x.test.again.dns in dns_again_means_nonexist? no (option unset)
>>> temporary error for host name lookup
>>> accept: condition test deferred in ACL "acl_V4NET_99_99"
LOG: H=[V4NET.99.99.96] F=<> temporarily rejected RCPT <x@y>: host lookup deferred for reverse lookup check
Expand All @@ -1159,6 +1154,7 @@ LOG: H=[V4NET.99.99.96] F=<> temporarily rejected RCPT <x@y>: host lookup deferr
>>> looking up host name for V4NET.99.99.96
>>> IP address lookup yielded "x.test.again.dns"
>>> x.test.again.dns in dns_again_means_nonexist? no (option unset)
>>> x.test.again.dns in dns_again_means_nonexist? no (option unset)
>>> temporary error for host name lookup
>>> accept: condition test succeeded in ACL "acl_V4NET_99_99"
>>> end of ACL "acl_V4NET_99_99": ACCEPT
Expand Down
Loading

0 comments on commit 1f155f8

Please sign in to comment.