dnslists: permit use with explicit key(s) in nonsmtp ACLs. Bug 1748
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 20 Dec 2015 20:01:52 +0000 (20:01 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 20 Dec 2015 23:33:19 +0000 (23:33 +0000)
doc/doc-txt/ChangeLog
src/src/acl.c
src/src/functions.h
src/src/verify.c
test/confs/0571 [new file with mode: 0644]
test/log/0571 [new file with mode: 0644]
test/rejectlog/0571 [new file with mode: 0644]
test/scripts/0000-Basic/0571 [new file with mode: 0644]

index 6976d4b..03a4ced 100644 (file)
@@ -137,6 +137,9 @@ JH/31 Fix bug with hosts_connection_nolog and named-lists which were wrongly
 JH/32 Move Redis support from Experimental to mainline, enabled for a build
       by defining LOOKUP_REDIS. The libhiredis library is required.
 
+JH/33 Bug 1748: Permit ACL dnslists= condition in non-smtp ACLs if explicit
+      keys are given for lookup.
+
 
 Exim version 4.86
 -----------------
index 17f55c2..1456cc7 100644 (file)
@@ -475,8 +475,10 @@ static unsigned int cond_forbids[] = {
   ~(1<<ACL_WHERE_DATA),                            /* dmarc_status */
   #endif
 
-  (1<<ACL_WHERE_NOTSMTP)|                          /* dnslists */
-    (1<<ACL_WHERE_NOTSMTP_START),
+  /* Explicit key lookups can be made in non-smtp ACLs so pass
+  always and check in the verify processing itself. */
+
+  0,                                              /* dnslists */
 
   (unsigned int)
   ~((1<<ACL_WHERE_RCPT)                            /* domains */
@@ -3567,7 +3569,7 @@ for (; cb != NULL; cb = cb->next)
     #endif
 
     case ACLC_DNSLISTS:
-    rc = verify_check_dnsbl(&arg);
+    rc = verify_check_dnsbl(where, &arg, log_msgptr);
     break;
 
     case ACLC_DOMAINS:
index bd43934..3b70087 100644 (file)
@@ -480,7 +480,7 @@ extern void    utf8_version_report(FILE *);
 
 extern int     verify_address(address_item *, FILE *, int, int, int, int,
                  uschar *, uschar *, BOOL *);
-extern int     verify_check_dnsbl(const uschar **);
+extern int     verify_check_dnsbl(int, const uschar **, uschar **);
 extern int     verify_check_header_address(uschar **, uschar **, int, int, int,
                  uschar *, uschar *, int, int *);
 extern int     verify_check_headers(uschar **);
index b73f45a..ef95394 100644 (file)
@@ -3876,7 +3876,9 @@ Note: an address for testing DUL is 192.203.178.4
 Note: a domain for testing RFCI is example.tld.dsn.rfc-ignorant.org
 
 Arguments:
+  where        the acl type
   listptr      the domain/address/data list
+  log_msgptr   log message on error
 
 Returns:    OK      successful lookup (i.e. the address is on the list), or
                       lookup deferred after +include_unknown
@@ -3886,7 +3888,7 @@ Returns:    OK      successful lookup (i.e. the address is on the list), or
 */
 
 int
-verify_check_dnsbl(const uschar **listptr)
+verify_check_dnsbl(int where, const uschar ** listptr, uschar ** log_msgptr)
 {
 int sep = 0;
 int defer_return = FAIL;
@@ -3933,21 +3935,19 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
 
   /* See if there's explicit data to be looked up */
 
-  key = Ustrchr(domain, '/');
-  if (key != NULL) *key++ = 0;
+  if ((key = Ustrchr(domain, '/'))) *key++ = 0;
 
   /* See if there's a list of addresses supplied after the domain name. This is
   introduced by an = or a & character; if preceded by = we require all matches
   and if preceded by ! we invert the result. */
 
-  iplist = Ustrchr(domain, '=');
-  if (iplist == NULL)
+  if (!(iplist = Ustrchr(domain, '=')))
     {
     bitmask = TRUE;
     iplist = Ustrchr(domain, '&');
     }
 
-  if (iplist != NULL)                          /* Found either = or & */
+  if (iplist)                                 /* Found either = or & */
     {
     if (iplist > domain && iplist[-1] == '!')  /* Handle preceding ! */
       {
@@ -3966,6 +3966,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
       }
     }
 
+
   /* If there is a comma in the domain, it indicates that a second domain for
   looking up TXT records is provided, before the main domain. Otherwise we must
   set domain_txt == domain. */
@@ -4011,6 +4012,13 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
 
   if (key == NULL)
     {
+    if (where == ACL_WHERE_NOTSMTP_START || where == ACL_WHERE_NOTSMTP)
+      {
+      *log_msgptr = string_sprintf
+       ("cannot test auto-keyed dnslists condition in %s ACL",
+         acl_wherenames[where]);
+      return ERROR;
+      }
     if (sender_host_address == NULL) return FAIL;    /* can never match */
     if (revadd[0] == 0) invert_address(revadd, sender_host_address);
     rc = one_check_dnsbl(domain, domain_txt, sender_host_address, revadd,
diff --git a/test/confs/0571 b/test/confs/0571
new file mode 100644 (file)
index 0000000..64383cd
--- /dev/null
@@ -0,0 +1,78 @@
+# Exim test configuration 0571
+
+LOG_SELECTOR=
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+tls_advertise_hosts =
+
+# ----- Main settings -----
+
+disable_ipv6 = true
+
+addresslist ok_senders = ok@ok.ok
+
+domainlist local_domains = test.ex : *.test.ex
+
+qualify_domain = test.ex
+trusted_users = CALLER
+
+# Use first three components of from_domain to select ACL
+acl_not_smtp =  ${if def:sender_address \
+       {acl_${sg{${tr{$sender_address_domain}{.}{_}}}{^(.*)_.*\$}{\$1}}} \
+       {accept control=queue_only}}
+
+# ----- ACLs -----
+
+begin acl
+
+acl_29_29_29:
+  deny    dnslists = test.ex/$sender_address_domain
+  accept
+
+acl_29_29_0:
+  deny    dnslists = test.ex
+  accept
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = appendfile
+  file = DIR/test-mail/$local_part
+  user = CALLER
+
+t2:
+  driver = appendfile
+  file = DIR/test-mail/okbatch
+  user = CALLER
+  batch_max = 100
+  envelope_to_add
+
+# ----- Routers -----
+
+begin routers
+
+r0:
+  driver = accept
+  local_parts = ^ok
+  transport = t2
+
+r1:
+  driver = accept
+  local_parts = ^userx : ^cond-
+  transport = t1
+
+r2:
+  driver = redirect
+  local_parts = fail
+  allow_fail
+  data = :fail: here is a fail message
+
+# End
diff --git a/test/log/0571 b/test/log/0571
new file mode 100644 (file)
index 0000000..fc7dd50
--- /dev/null
@@ -0,0 +1,4 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 F=<ted@29.29.0.com> rejected by non-SMTP ACL: cannot test keyless dnslists condition in non-SMTP ACL
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> R=10HmaX-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmaY-0005vi-00 no immediate delivery: queued by ACL
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= bill@29.29.29.com U=CALLER P=local S=sss
diff --git a/test/rejectlog/0571 b/test/rejectlog/0571
new file mode 100644 (file)
index 0000000..494bffe
--- /dev/null
@@ -0,0 +1,10 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 F=<ted@29.29.0.com> rejected by non-SMTP ACL: cannot test keyless dnslists condition in non-SMTP ACL
+Envelope-from: <ted@29.29.0.com>
+Envelope-to: <ok1@test.ex>
+P Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <ted@29.29.0.com>)
+       id 10HmaX-0005vi-00
+       for ok1@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+I Message-Id: <E10HmaX-0005vi-00@myhost.test.ex>
+F From: ted@29.29.0.com
+  Date: Tue, 2 Mar 1999 09:44:33 +0000
diff --git a/test/scripts/0000-Basic/0571 b/test/scripts/0000-Basic/0571
new file mode 100644 (file)
index 0000000..3eab04c
--- /dev/null
@@ -0,0 +1,14 @@
+# ACL - dnslists in non-smtp ACL
+#
+1
+exim -f ted@29.29.0.com -odq ok1@test.ex
+should fail
+.
+****
+#
+exim -f bill@29.29.29.com -odq ok1@test.ex
+should pass
+.
+****
+#
+no_msglog_check