Downgrade an unfound-list name from panic to DEFER. Bug 1645
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 11 Nov 2017 16:11:06 +0000 (16:11 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 11 Nov 2017 16:11:06 +0000 (16:11 +0000)
doc/doc-txt/ChangeLog
src/src/match.c
test/confs/0275
test/scripts/0000-Basic/0275
test/stderr/0275
test/stdout/0275

index fd188a0..00377b9 100644 (file)
@@ -186,6 +186,13 @@ JH/32 DKIM: when a message has multiple signatures matching an identity given
       in dkim_verify_signers, run the dkim acl once for each.  Previously only
       one run was done.  Bug 2189.
 
+JH/33 Downgrade an unfound-list name (usually a typo in the config file) from
+      "panic the current process" to "deliberately defer".  The panic log is
+      still written with the problem list name; the mail and reject logs now
+      get a temp-reject line for the message that was being handled, saying
+      something like "domains check lookup or other defer".  The SMTP 451
+      message is still "Temporary local problem".
+
 
 Exim version 4.89
 -----------------
index c217114..08ec0ee 100644 (file)
@@ -461,12 +461,9 @@ HDEBUG(D_any)
 /* If the list is empty, the answer is no. Skip the debugging output for
 an unnamed list. */
 
-if (*listptr == NULL)
+if (!*listptr)
   {
-  HDEBUG(D_lists)
-    {
-    if (ot != NULL) debug_printf("%s no (option unset)\n", ot);
-    }
+  HDEBUG(D_lists) if (ot) debug_printf("%s no (option unset)\n", ot);
   return FAIL;
   }
 
@@ -485,17 +482,17 @@ else
   /* If we are searching a domain list, and $domain is not set, set it to the
   subject that is being sought for the duration of the expansion. */
 
-  if (type == MCL_DOMAIN && deliver_domain == NULL)
+  if (type == MCL_DOMAIN && !deliver_domain)
     {
     check_string_block *cb = (check_string_block *)arg;
     deliver_domain = string_copy(cb->subject);
     list = expand_cstring(*listptr);
     deliver_domain = NULL;
     }
+  else
+    list = expand_cstring(*listptr);
 
-  else list = expand_cstring(*listptr);
-
-  if (list == NULL)
+  if (!list)
     {
     if (expand_string_forcedfail)
       {
@@ -511,17 +508,14 @@ else
 
 /* For an unnamed list, use the expanded version in comments */
 
-HDEBUG(D_any)
-  {
-  if (ot == NULL) ot = string_sprintf("%s in \"%s\"?", name, list);
-  }
+HDEBUG(D_any) if (ot == NULL) ot = string_sprintf("%s in \"%s\"?", name, list);
 
 /* Now scan the list and process each item in turn, until one of them matches,
 or we hit an error. */
 
-while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
+while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
   {
-  uschar *ss = sss;
+  uschar * ss = sss;
 
   /* Address lists may contain +caseful, to restore caseful matching of the
   local part. We have to know the layout of the control block, unfortunately.
@@ -534,7 +528,8 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
       {
       check_address_block *cb = (check_address_block *)arg;
       uschar *at = Ustrrchr(cb->origaddress, '@');
-      if (at != NULL)
+
+      if (at)
         Ustrncpy(cb->address, cb->origaddress, at - cb->origaddress);
       cb->caseless = FALSE;
       continue;
@@ -594,7 +589,8 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
     yield = FAIL;
     while (isspace((*(++ss))));
     }
-  else yield = OK;
+  else
+    yield = OK;
 
   /* If the item does not begin with '/', it might be a + item for a named
   list. Otherwise, it is just a single list entry that has to be matched.
@@ -602,7 +598,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
 
   if (*ss != '/')
     {
-    if (*ss == '+' && anchorptr != NULL)
+    if (*ss == '+' && anchorptr)
       {
       int bits = 0;
       int offset = 0;
@@ -610,15 +606,18 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
       unsigned int *use_cache_bits = original_cache_bits;
       uschar *cached = US"";
       namedlist_block *nb;
-      tree_node *t = tree_search(*anchorptr, ss+1);
-
-      if (t == NULL)
-        log_write(0, LOG_MAIN|LOG_PANIC_DIE, "unknown named%s list \"%s\"",
-          (type == MCL_DOMAIN)?    " domain" :
-          (type == MCL_HOST)?      " host" :
-          (type == MCL_ADDRESS)?   " address" :
-          (type == MCL_LOCALPART)? " local part" : "",
+      tree_node * t;
+
+      if (!(t = tree_search(*anchorptr, ss+1)))
+       {
+        log_write(0, LOG_MAIN|LOG_PANIC, "unknown named%s list \"%s\"",
+          type == MCL_DOMAIN ?    " domain" :
+          type == MCL_HOST ?      " host" :
+          type == MCL_ADDRESS ?   " address" :
+          type == MCL_LOCALPART ? " local part" : "",
           ss);
+       return DEFER;
+       }
       nb = t->data.ptr;
 
       /* If the list number is negative, it means that this list is not
@@ -630,7 +629,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
       because the pointer may be NULL from the start if caching is not
       required. */
 
-      if (use_cache_bits != NULL)
+      if (use_cache_bits)
         {
         offset = (nb->number)/16;
         shift = ((nb->number)%16)*2;
@@ -654,15 +653,13 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         wasn't before. Ensure that this is passed up to the next level.
         Otherwise, remember the result of the search in the cache. */
 
-        if (use_cache_bits == NULL)
-          {
+        if (!use_cache_bits)
           *cache_ptr = NULL;
-          }
         else
           {
           use_cache_bits[offset] |= bits << shift;
 
-          if (valueptr != NULL)
+          if (valueptr)
             {
             int old_pool = store_pool;
             namedlist_cacheblock *p;
@@ -675,16 +672,14 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
             p->key = string_copy(get_check_key(arg, type));
 
 
-            p->data = (*valueptr == NULL)? NULL : string_copy(*valueptr);
+            p->data = *valueptr ? string_copy(*valueptr) : NULL;
             store_pool = old_pool;
 
             p->next = nb->cache_data;
             nb->cache_data = p;
-            if (*valueptr != NULL)
-              {
+            if (*valueptr)
               DEBUG(D_lists) debug_printf("data from lookup saved for "
                 "cache for %s: %s\n", ss, *valueptr);
-              }
             }
           }
         }
@@ -697,19 +692,18 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         {
         DEBUG(D_lists) debug_printf("cached %s match for %s\n",
           ((bits & (-bits)) == bits)? "yes" : "no", ss);
+
         cached = US" - cached";
-        if (valueptr != NULL)
+        if (valueptr)
           {
           const uschar *key = get_check_key(arg, type);
           namedlist_cacheblock *p;
-          for (p = nb->cache_data; p != NULL; p = p->next)
-            {
+          for (p = nb->cache_data; p; p = p->next)
             if (Ustrcmp(key, p->key) == 0)
               {
               *valueptr = p->data;
               break;
               }
-            }
           DEBUG(D_lists) debug_printf("cached lookup data = %s\n", *valueptr);
           }
         }
@@ -729,30 +723,30 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
 
     else
       {
-      uschar *error = NULL;
+      uschar * error = NULL;
       switch ((func)(arg, ss, valueptr, &error))
         {
         case OK:
-        HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\")\n", ot,
-          (yield == OK)? "yes" : "no", sss);
-        return yield;
+         HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\")\n", ot,
+           (yield == OK)? "yes" : "no", sss);
+         return yield;
 
         case DEFER:
-        if (error == NULL)
-          error = string_sprintf("DNS lookup of \"%s\" deferred", ss);
-        if (ignore_defer)
-          {
-          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n",
-            error);
-          break;
-          }
-        if (include_defer)
-          {
-          log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
-          return OK;
-          }
-        if (!search_error_message) search_error_message = error;
-        goto DEFER_RETURN;
+         if (!error)
+           error = string_sprintf("DNS lookup of \"%s\" deferred", ss);
+         if (ignore_defer)
+           {
+           HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n",
+             error);
+           break;
+           }
+         if (include_defer)
+           {
+           log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
+           return OK;
+           }
+         if (!search_error_message) search_error_message = error;
+         goto DEFER_RETURN;
 
         /* The ERROR return occurs when checking hosts, when either a forward
         or reverse lookup has failed. It can also occur in a match_ip list if a
@@ -760,24 +754,24 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         which it was. */
 
         case ERROR:
-        if (ignore_unknown)
-          {
-          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n",
-            error);
-          }
-        else
-          {
-          HDEBUG(D_lists) debug_printf("%s %s (%s)\n", ot,
-            include_unknown? "yes":"no", error);
-          if (!include_unknown)
-            {
-            if (LOGGING(unknown_in_list))
-              log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
-            return FAIL;
-            }
-          log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
-          return OK;
-          }
+         if (ignore_unknown)
+           {
+           HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n",
+             error);
+           }
+         else
+           {
+           HDEBUG(D_lists) debug_printf("%s %s (%s)\n", ot,
+             include_unknown? "yes":"no", error);
+           if (!include_unknown)
+             {
+             if (LOGGING(unknown_in_list))
+               log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
+             return FAIL;
+             }
+           log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
+           return OK;
+           }
         }
       }
     }
@@ -788,16 +782,16 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
   else
     {
     int file_yield = yield;       /* In case empty file */
-    uschar *filename = ss;
-    FILE *f = Ufopen(filename, "rb");
+    uschar * filename = ss;
+    FILE * f = Ufopen(filename, "rb");
     uschar filebuffer[1024];
 
     /* ot will be null in non-debugging cases, and anyway, we get better
     wording by reworking it. */
 
-    if (f == NULL)
+    if (!f)
       {
-      uschar *listname = readconf_find_option(listptr);
+      uschar * listname = readconf_find_option(listptr);
       if (listname[0] == 0)
         listname = string_sprintf("\"%s\"", *listptr);
       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
@@ -845,48 +839,48 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
       switch ((func)(arg, ss, valueptr, &error))
         {
         case OK:
-        (void)fclose(f);
-        HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\" in %s)\n", ot,
-          (yield == OK)? "yes" : "no", sss, filename);
-        return file_yield;
+         (void)fclose(f);
+         HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\" in %s)\n", ot,
+           yield == OK ? "yes" : "no", sss, filename);
+         return file_yield;
 
         case DEFER:
-        if (error == NULL)
-          error = string_sprintf("DNS lookup of %s deferred", ss);
-        if (ignore_defer)
-          {
-          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n",
-            error);
-          break;
-          }
-        (void)fclose(f);
-        if (include_defer)
-          {
-          log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
-          return OK;
-          }
-        goto DEFER_RETURN;
-
-        case ERROR:          /* host name lookup failed - this can only */
-        if (ignore_unknown)  /* be for an incoming host (not outgoing) */
-          {
-          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n",
-            error);
-          }
-        else
-         {
-          HDEBUG(D_lists) debug_printf("%s %s (%s)\n", ot,
-            include_unknown? "yes":"no", error);
-          (void)fclose(f);
-          if (!include_unknown)
-            {
-            if (LOGGING(unknown_in_list))
-              log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
-            return FAIL;
-            }
-          log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
-          return OK;
-          }
+         if (!error)
+           error = string_sprintf("DNS lookup of %s deferred", ss);
+         if (ignore_defer)
+           {
+           HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n",
+             error);
+           break;
+           }
+         (void)fclose(f);
+         if (include_defer)
+           {
+           log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
+           return OK;
+           }
+         goto DEFER_RETURN;
+
+        case ERROR:            /* host name lookup failed - this can only */
+         if (ignore_unknown)   /* be for an incoming host (not outgoing) */
+           {
+           HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n",
+             error);
+           }
+         else
+          {
+           HDEBUG(D_lists) debug_printf("%s %s (%s)\n", ot,
+             include_unknown? "yes":"no", error);
+           (void)fclose(f);
+           if (!include_unknown)
+             {
+             if (LOGGING(unknown_in_list))
+               log_write(0, LOG_MAIN, "list matching forced to fail: %s", error);
+             return FAIL;
+             }
+           log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error);
+           return OK;
+           }
         }
       }
 
@@ -901,8 +895,8 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
 /* End of list reached: if the last item was negated yield OK, else FAIL. */
 
 HDEBUG(D_lists)
-  debug_printf("%s %s (end of list)\n", ot, (yield == OK)? "no":"yes");
-return (yield == OK)? FAIL : OK;
+  debug_printf("%s %s (end of list)\n", ot, yield == OK ? "no":"yes");
+return yield == OK ? FAIL : OK;
 
 /* Something deferred */
 
index 3734e03..7117d51 100644 (file)
@@ -6,6 +6,8 @@ primary_hostname = myhost.test.ex
 
 # ----- Main settings -----
 
+acl_smtp_rcpt = accept verify = recipient
+
 domainlist nocache = $local_part
 domainlist nocache2 = +nocache
 domainlist local_domains = test.ex
@@ -36,6 +38,14 @@ t1:
 
 begin routers
 
+.ifdef FAKE
+r0f:
+  driver = accept
+  local_parts = error
+  domains = +no_such_list
+  transport = t1
+.endif
+
 r00:
   driver = accept
   domains = +nocache
index 410efa8..953ab7e 100644 (file)
@@ -1,5 +1,14 @@
 # named domain lists
 exim -d -bt userx@test.ex
 ****
+#
 exim -d -odi userx@test.ex
 ****
+#
+exim -d -DFAKE -bh 127.0.0.1
+HELO test
+MAIL FROM:<test@test.ex>
+RCPT TO:<error@test.ex>
+QUIT
+****
+#
index b663ad4..f34132b 100644 (file)
@@ -357,3 +357,81 @@ search_tidyup called
 >>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
 search_tidyup called
 >>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
+Exim version x.yz ....
+changed uid/gid: forcing real = effective
+  uid=uuuu gid=CALLER_GID pid=pppp
+configuration file is TESTSUITE/test-config
+admin user
+changed uid/gid: privilege not needed
+  uid=EXIM_UID gid=EXIM_GID pid=pppp
+seeking password data for user "CALLER": cache not available
+getpwnam() succeeded uid=CALLER_UID gid=CALLER_GID
+DSN: r0f propagating DSN
+DSN: r00 propagating DSN
+DSN: r01 propagating DSN
+DSN: r02 propagating DSN
+DSN: r03 propagating DSN
+DSN: r04 propagating DSN
+DSN: r05 propagating DSN
+DSN: r1 propagating DSN
+DSN: r2 propagating DSN
+DSN: r3 propagating DSN
+originator: uid=CALLER_UID gid=CALLER_GID login=CALLER name=CALLER_NAME
+sender address = CALLER@test.ex
+sender_fullhost = [127.0.0.1]
+sender_rcvhost = [127.0.0.1]
+host in hosts_connection_nolog? no (option unset)
+LOG: smtp_connection MAIN
+  SMTP connection from [127.0.0.1]
+host in host_lookup? no (option unset)
+set_process_info: pppp handling incoming connection from [127.0.0.1]
+host in host_reject_connection? no (option unset)
+host in sender_unqualified_hosts? no (option unset)
+host in recipient_unqualified_hosts? no (option unset)
+host in helo_verify_hosts? no (option unset)
+host in helo_try_verify_hosts? no (option unset)
+host in helo_accept_junk_hosts? no (option unset)
+SMTP>> 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+smtp_setup_msg entered
+SMTP<< HELO test
+test in helo_lookup_domains? no (end of list)
+sender_fullhost = (test) [127.0.0.1]
+sender_rcvhost = [127.0.0.1] (helo=test)
+set_process_info: pppp handling incoming connection from (test) [127.0.0.1]
+SMTP>> 250 myhost.test.ex Hello test [127.0.0.1]
+SMTP<< MAIL FROM:<test@test.ex>
+spool directory space = nnnnnK inodes = nnnnn check_space = 10240K inodes = 100 msg_size = 0
+log directory space = nnnnnK inodes = nnnnn check_space = 10240K inodes = 100
+SMTP>> 250 OK
+SMTP<< RCPT TO:<error@test.ex>
+test.ex in "! *.ex"? no (matched "! *.ex")
+test.ex in "test.ex"? yes (matched "test.ex")
+test.ex in percent_hack_domains? yes (matched "+not_queue_domains")
+processing "accept"
+check verify = recipient
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+Verifying error@test.ex
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+Considering error@test.ex
+cached no match for +hold_domains
+cached yes match for +not_queue_domains
+test.ex in percent_hack_domains? yes (matched "+not_queue_domains" - cached)
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+routing error@test.ex
+--------> r0f router <--------
+local_part=error domain=test.ex
+checking domains
+LOG: MAIN PANIC
+  unknown named domain list "+no_such_list"
+domains check lookup or other defer
+----------- end verify ------------
+accept: condition test deferred in inline ACL
+SMTP>> 451 Temporary local problem - please try later
+LOG: MAIN REJECT
+  H=(test) [127.0.0.1] F=<test@test.ex> temporarily rejected RCPT <error@test.ex>: domains check lookup or other defer
+SMTP<< QUIT
+SMTP>> 221 myhost.test.ex closing connection
+LOG: smtp_connection MAIN
+  SMTP connection from (test) [127.0.0.1] closed by QUIT
+search_tidyup called
+>>>>>>>>>>>>>>>> Exim pid=pppp (main) terminating with rc=0 >>>>>>>>>>>>>>>>
index fa02efa..1642be1 100644 (file)
@@ -1,2 +1,12 @@
 userx@test.ex
   router = r3, transport = t1
+
+**** SMTP testing session as if from host 127.0.0.1
+**** but without any ident (RFC 1413) callback.
+**** This is not for real!
+
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250 myhost.test.ex Hello test [127.0.0.1]\r
+250 OK\r
+451 Temporary local problem - please try later\r
+221 myhost.test.ex closing connection\r