From: Jeremy Harris Date: Sun, 5 May 2024 17:11:45 +0000 (+0100) Subject: Events: dns:fail Bug 3011 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/HEAD Events: dns:fail Bug 3011 --- diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 1b4a2572d..af5f51d6c 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -43020,6 +43020,7 @@ The current list of events is: .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" @@ -43053,6 +43054,7 @@ with the event type: .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" diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 58ab945be..1781e05b1 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -13,13 +13,15 @@ Version 4.98 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 ------------ diff --git a/src/src/acl.c b/src/src/acl.c index d719a937b..4e88fc1ac 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -4450,7 +4450,7 @@ while ((acl_current = acl)) 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; } diff --git a/src/src/dns.c b/src/src/dns.c index 74c5a58c5..b22f4d327 100644 --- a/src/src/dns.c +++ b/src/src/dns.c @@ -1010,7 +1010,7 @@ won't return any. 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: @@ -1028,11 +1028,13 @@ Returns: DNS_SUCCEED successful lookup */ 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 @@ -1046,12 +1048,11 @@ for (int i = 0; i <= dns_cname_loops; i++) 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 @@ -1105,13 +1106,19 @@ for (int i = 0; i <= dns_cname_loops; i++) 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)) @@ -1120,11 +1127,48 @@ for (int i = 0; i <= dns_cname_loops; i++) 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; + } } diff --git a/test/confs/5708 b/test/confs/5708 new file mode 100644 index 000000000..4fc0e9b27 --- /dev/null +++ b/test/confs/5708 @@ -0,0 +1,32 @@ +# 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 diff --git a/test/confs/5709 b/test/confs/5709 new file mode 100644 index 000000000..e663b86b6 --- /dev/null +++ b/test/confs/5709 @@ -0,0 +1,8 @@ +# 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 diff --git a/test/log/5708 b/test/log/5708 new file mode 100644 index 000000000..89eba8107 --- /dev/null +++ b/test/log/5708 @@ -0,0 +1,16 @@ + +******** 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 +1999-03-02 09:44:33 M +1999-03-02 09:44:33 H=(nonexistent.test.ex) [127.0.0.1] F= rejected RCPT +1999-03-02 09:44:33 M +1999-03-02 09:44:33 M +1999-03-02 09:44:33 H=(badcname.test.ex) [127.0.0.1] F= rejected RCPT +1999-03-02 09:44:33 M +1999-03-02 09:44:33 M +1999-03-02 09:44:33 H=(test.again.dns) [127.0.0.1] F= rejected RCPT +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 +1999-03-02 09:44:33 10HmaX-000000005vi-0000 T +1999-03-02 09:44:33 10HmaX-000000005vi-0000 == bad_a@nonexistent.test.ex R=all T=all defer (-32): failed to lookup IP address for nonexistent.test.ex diff --git a/test/rejectlog/5708 b/test/rejectlog/5708 new file mode 100644 index 000000000..98f38cd91 --- /dev/null +++ b/test/rejectlog/5708 @@ -0,0 +1,5 @@ + +******** SERVER ******** +1999-03-02 09:44:33 H=(nonexistent.test.ex) [127.0.0.1] F= rejected RCPT +1999-03-02 09:44:33 H=(badcname.test.ex) [127.0.0.1] F= rejected RCPT +1999-03-02 09:44:33 H=(test.again.dns) [127.0.0.1] F= rejected RCPT diff --git a/test/scripts/5700-events/5708 b/test/scripts/5700-events/5708 new file mode 100644 index 000000000..9cb9508fe --- /dev/null +++ b/test/scripts/5700-events/5708 @@ -0,0 +1,62 @@ +# 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: +??? 250 +RCPT TO: +??? 550 +QUIT +??? 221 +**** +# CNAME to no-A-record +client 127.0.0.1 PORT_D +??? 220 +HELO badcname.test.ex +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 550 +QUIT +??? 221 +**** +# defer from dns lookup +client 127.0.0.1 PORT_D +??? 220 +HELO test.again.dns +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 550 +QUIT +??? 221 +**** +# success in RCPT ACL; no-A in transport +client 127.0.0.1 PORT_D +??? 220 +HELO localhost +??? 250 +MAIL FROM: +??? 250 +RCPT TO: +??? 250 Accepted +DATA +??? 354 +Subject: test +. +??? 250 +QUIT +??? 221 +**** +# +sleep 1 +killdaemon +no_msglog_check diff --git a/test/scripts/5709_dnsdb_events/5709 b/test/scripts/5709_dnsdb_events/5709 new file mode 100644 index 000000000..03ca7ed62 --- /dev/null +++ b/test/scripts/5709_dnsdb_events/5709 @@ -0,0 +1,8 @@ +# 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}} +**** diff --git a/test/scripts/5709_dnsdb_events/REQUIRES b/test/scripts/5709_dnsdb_events/REQUIRES new file mode 100644 index 000000000..22e09781c --- /dev/null +++ b/test/scripts/5709_dnsdb_events/REQUIRES @@ -0,0 +1,2 @@ +lookup dnsdb +support Event diff --git a/test/stderr/5709 b/test/stderr/5709 new file mode 100644 index 000000000..279f0ba66 --- /dev/null +++ b/test/stderr/5709 @@ -0,0 +1,3 @@ +1999-03-02 09:44:33 +1999-03-02 09:44:33 +1999-03-02 09:44:33 diff --git a/test/stdout/5708 b/test/stdout/5708 new file mode 100644 index 000000000..d2c78b4a2 --- /dev/null +++ b/test/stdout/5708 @@ -0,0 +1,71 @@ +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: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 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: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 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: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 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: +??? 250 +<<< 250 OK +>>> RCPT TO: +??? 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 diff --git a/test/stdout/5709 b/test/stdout/5709 new file mode 100644 index 000000000..c1a7fdeb8 --- /dev/null +++ b/test/stdout/5709 @@ -0,0 +1,5 @@ +> bad_a FAIL +> badcname FAIL +> Failed: lookup of "a=test.again.dns" gave DEFER: +> good A TXT record for test.ex. +>