.itable all 0 0 4 25* left 10* center 15* center 50* left
.row auth:fail after both "per driver per authentication attempt"
.row dane:fail after transport "per connection"
+.row dns:fail after both "per lookup"
.row msg:complete after main "per message"
.row msg:defer after transport "per message per delivery try"
.row msg:delivery after transport "per recipient"
.itable all 0 0 2 20* left 80* left
.row auth:fail "smtp response"
.row dane:fail "failure reason"
+.row dns:fail "failure reason, key and lookup-type"
.row msg:defer "error string"
.row msg:delivery "smtp confirmation message"
.row msg:fail:internal "failure reason"
2. The dkim_verbose logging control also enables logging of signing
3. The dkim_timestamps signing option now accepts zero to include a current
- timestamp but no extiry timestamp. Code by Simon Arlott; testsuite
+ timestamp but no expiry timestamp. Code by Simon Arlott; testsuite
additions by jgh.
4. The recipients_max main option is now expanded.
5. Setting variables for "exim -be" can set a tainted value.
+ 6. A dns:fail event.
+
Version 4.97
------------
verbs[acl->verb], acl_name);
if (basic_errno != ERRNO_CALLOUTDEFER)
{
- if (search_error_message != NULL && *search_error_message != 0)
+ if (search_error_message && *search_error_message)
*log_msgptr = search_error_message;
if (smtp_return_error_details) f.acl_temp_details = TRUE;
}
If fully_qualified_name is not NULL, set it to point to the full name
returned by the resolver, if this is different to what it is given, unless
the returned name starts with "*" as some nameservers seem to be returning
-wildcards in this form. In international mode "different" means "alabel
+wildcards in this form. In international mode "different" means "a-label
forms are different".
Arguments:
*/
int
-dns_lookup(dns_answer *dnsa, const uschar *name, int type,
- const uschar **fully_qualified_name)
+dns_lookup(dns_answer * dnsa, const uschar * name, int type,
+ const uschar ** fully_qualified_name)
{
-const uschar *orig_name = name;
+const uschar * orig_name = name;
BOOL secure_so_far = TRUE;
+int rc = DNS_FAIL;
+const uschar * errstr = NULL;
/* By default, assume the resolver follows CNAME chains (and returns NODATA for
an unterminated one). If it also does that for a CNAME loop, fine; if it returns
uschar * data;
dns_record cname_rr, type_rr;
dns_scan dnss;
- int rc;
/* DNS lookup failures get passed straight back. */
if ((rc = dns_basic_lookup(dnsa, name, type)) != DNS_SUCCEED)
- return rc;
+ goto not_good;
/* We should have either records of the required type, or a CNAME record,
or both. We need to know whether both exist for getting the fully qualified
its not existing. */
if (!cname_rr.data)
- return DNS_FAIL;
+ {
+ errstr = US"no_hit_yet_no_cname";
+ goto not_good;
+ }
/* DNS data comes from the outside, hence tainted */
data = store_get(256, GET_TAINTED);
if (dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
cname_rr.data, (DN_EXPAND_ARG4_TYPE)data, 256) < 0)
- return DNS_FAIL;
+ {
+ errstr = US"bad_expand";
+ goto not_good;
+ }
name = data;
if (!dns_is_secure(dnsa))
DEBUG(D_dns) debug_printf("CNAME found: change to %s\n", name);
} /* Loop back to do another lookup */
-/*Control reaches here after 10 times round the CNAME loop. Something isn't
+/* Control reaches here after 10 times round the CNAME loop. Something isn't
right... */
log_write(0, LOG_MAIN, "CNAME loop for %s encountered", orig_name);
-return DNS_FAIL;
+errstr = US"cname_loop";
+
+not_good:
+ {
+ const uschar * s = NULL;
+ BOOL save_flag = f.search_find_defer;
+ uschar * save_serr = search_error_message;
+
+ if (!transport_name)
+ s = event_action;
+ else
+ for(transport_instance * tp = transports; tp; tp = tp->next)
+ if (Ustrcmp(tp->name, transport_name) == 0)
+ { s = tp->event_action; break; }
+
+ if (s)
+ {
+ if (Ustrchr(name, ':')) /* unlikely, but may as well bugproof */
+ {
+ gstring * g = NULL;
+ while (*name)
+ {
+ if (*name == ':') g = string_catn(g, name, 1);
+ g = string_catn(g, name++, 1);
+ }
+ name = string_from_gstring(g);
+ }
+ event_raise(s, US"dns:fail",
+ string_sprintf("%s:%s:%s",
+ errstr ? errstr : dns_rc_names[rc], name, dns_text_type(type)),
+ NULL);
+ }
+
+ /*XXX what other state could an expansion in the eventhandler mess up? */
+ search_error_message = save_serr;
+ f.search_find_defer = save_flag;
+ return rc;
+ }
}
--- /dev/null
+# Exim test configuration 5708
+# Check for event on dns lookup fail
+
+.include DIR/aux-var/std_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = accept verify = helo
+
+event_action = ${acl {accept logwrite = M <$event_name> <$event_data>}}
+
+# ----- Routers -----
+begin routers
+all:
+ driver = accept
+ transport = all
+ errors_to = ""
+
+# ----- Transports -----
+begin transports
+all:
+ driver = smtp
+ hosts = ${if inlist {$domain} {nonexistent.test.ex} {$value}}
+ event_action = ${acl {accept logwrite = T <$event_name> <$event_data>}}
+
+# ------ Retries ----
+begin retry
+* * F,10m,2d
+
+# End
--- /dev/null
+# Exim test configuration 5709
+# Check for event on dnsdb lookup fail
+
+.include DIR/aux-var/std_conf_prefix
+primary_hostname = myhost.test.ex
+event_action = ${acl {accept logwrite = <$event_name> <$event_data>}}
+
+# End
--- /dev/null
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=p1234, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 M <dns:fail> <DNS_NOMATCH:nonexistent.test.ex:AAAA>
+1999-03-02 09:44:33 M <dns:fail> <DNS_NOMATCH:nonexistent.test.ex:A>
+1999-03-02 09:44:33 H=(nonexistent.test.ex) [127.0.0.1] F=<a@b> rejected RCPT <c@d>
+1999-03-02 09:44:33 M <dns:fail> <DNS_NOMATCH:rhubarb.test.ex:AAAA>
+1999-03-02 09:44:33 M <dns:fail> <DNS_NOMATCH:rhubarb.test.ex:A>
+1999-03-02 09:44:33 H=(badcname.test.ex) [127.0.0.1] F=<a@b> rejected RCPT <c@d>
+1999-03-02 09:44:33 M <dns:fail> <DNS_AGAIN:test.again.dns:AAAA>
+1999-03-02 09:44:33 M <dns:fail> <DNS_AGAIN:test.again.dns:A>
+1999-03-02 09:44:33 H=(test.again.dns) [127.0.0.1] F=<a@b> rejected RCPT <c@d>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= a@b H=(localhost) [127.0.0.1] P=smtp S=sss
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 T <dns:fail> <DNS_NOMATCH:nonexistent.test.ex:AAAA>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 T <dns:fail> <DNS_NOMATCH:nonexistent.test.ex:A>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 == bad_a@nonexistent.test.ex <bad_A@nonexistent.test.ex> R=all T=all defer (-32): failed to lookup IP address for nonexistent.test.ex
--- /dev/null
+
+******** SERVER ********
+1999-03-02 09:44:33 H=(nonexistent.test.ex) [127.0.0.1] F=<a@b> rejected RCPT <c@d>
+1999-03-02 09:44:33 H=(badcname.test.ex) [127.0.0.1] F=<a@b> rejected RCPT <c@d>
+1999-03-02 09:44:33 H=(test.again.dns) [127.0.0.1] F=<a@b> rejected RCPT <c@d>
--- /dev/null
+# event on dns lookup fail
+
+exim -bd -DSERVER=server -oX PORT_D
+****
+#
+# no A record
+client 127.0.0.1 PORT_D
+??? 220
+HELO nonexistent.test.ex
+??? 250
+MAIL FROM:<a@b>
+??? 250
+RCPT TO:<c@d>
+??? 550
+QUIT
+??? 221
+****
+# CNAME to no-A-record
+client 127.0.0.1 PORT_D
+??? 220
+HELO badcname.test.ex
+??? 250
+MAIL FROM:<a@b>
+??? 250
+RCPT TO:<c@d>
+??? 550
+QUIT
+??? 221
+****
+# defer from dns lookup
+client 127.0.0.1 PORT_D
+??? 220
+HELO test.again.dns
+??? 250
+MAIL FROM:<a@b>
+??? 250
+RCPT TO:<c@d>
+??? 550
+QUIT
+??? 221
+****
+# success in RCPT ACL; no-A in transport
+client 127.0.0.1 PORT_D
+??? 220
+HELO localhost
+??? 250
+MAIL FROM:<a@b>
+??? 250
+RCPT TO:<bad_A@nonexistent.test.ex>
+??? 250 Accepted
+DATA
+??? 354
+Subject: test
+.
+??? 250
+QUIT
+??? 221
+****
+#
+sleep 1
+killdaemon
+no_msglog_check
--- /dev/null
+# event on dnsdb lookup fail
+
+exim -be
+bad_a ${lookup dnsdb{a=nonexistent.test.ex}{$value}{FAIL}}
+badcname ${lookup dnsdb{a=badcname.test.ex}{$value}{FAIL}}
+defer ${lookup dnsdb{a=test.again.dns}{$value}{FAIL}}
+good ${lookup dnsdb{txt=test.ex}{$value}{FAIL}}
+****
--- /dev/null
+lookup dnsdb
+support Event
--- /dev/null
+1999-03-02 09:44:33 <dns:fail> <DNS_NOMATCH:nonexistent.test.ex:A>
+1999-03-02 09:44:33 <dns:fail> <DNS_NOMATCH:rhubarb.test.ex:A>
+1999-03-02 09:44:33 <dns:fail> <DNS_AGAIN:test.again.dns:A>
--- /dev/null
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> HELO nonexistent.test.ex
+??? 250
+<<< 250 myhost.test.ex Hello nonexistent.test.ex [127.0.0.1]
+>>> MAIL FROM:<a@b>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<c@d>
+??? 550
+<<< 550 Administrative prohibition
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> HELO badcname.test.ex
+??? 250
+<<< 250 myhost.test.ex Hello badcname.test.ex [127.0.0.1]
+>>> MAIL FROM:<a@b>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<c@d>
+??? 550
+<<< 550 Administrative prohibition
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> HELO test.again.dns
+??? 250
+<<< 250 myhost.test.ex Hello test.again.dns [127.0.0.1]
+>>> MAIL FROM:<a@b>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<c@d>
+??? 550
+<<< 550 Administrative prohibition
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> HELO localhost
+??? 250
+<<< 250 myhost.test.ex Hello localhost [127.0.0.1]
+>>> MAIL FROM:<a@b>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<bad_A@nonexistent.test.ex>
+??? 250 Accepted
+<<< 250 Accepted
+>>> DATA
+??? 354
+<<< 354 Enter message, ending with "." on a line by itself
+>>> Subject: test
+>>> .
+??? 250
+<<< 250 OK id=10HmaX-000000005vi-0000
+>>> QUIT
+??? 221
+<<< 221 myhost.test.ex closing connection
+End of script
--- /dev/null
+> bad_a FAIL
+> badcname FAIL
+> Failed: lookup of "a=test.again.dns" gave DEFER:
+> good A TXT record for test.ex.
+>