TLS: Session resumption, under the EXPERIMENTAL_TLS_RESUME build option.
[exim.git] / src / src / acl.c
index f3b860e4af33eedb3dcf3f8e8a29f2e1939e3c14..19938affac44b7a948012950b2cdd4d31545b2bc 100644 (file)
@@ -367,9 +367,6 @@ enum {
   CONTROL_NO_PIPELINING,
 
   CONTROL_QUEUE_ONLY,
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
-  CONTROL_REQUIRETLS,
-#endif
   CONTROL_SUBMISSION,
   CONTROL_SUPPRESS_LOCAL_FIXUPS,
 #ifdef SUPPORT_I18N
@@ -515,16 +512,6 @@ static control_def controls_list[] = {
   },
 
 
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
-[CONTROL_REQUIRETLS] =
-  { US"requiretls",             FALSE,
-         (unsigned)
-         ~(ACL_BIT_MAIL | ACL_BIT_RCPT | ACL_BIT_PREDATA |
-           ACL_BIT_DATA | ACL_BIT_MIME |
-           ACL_BIT_NOTSMTP)
-  },
-#endif
-
 [CONTROL_SUBMISSION] =
   { US"submission",              TRUE,
          (unsigned)
@@ -643,8 +630,7 @@ Returns:    index of a control entry, or -1 if not found
 static int
 find_control(const uschar * name, control_def * ol, int last)
 {
-int first = 0;
-while (last > first)
+for (int first = 0; last > first; )
   {
   int middle = (first + last)/2;
   uschar * s =  ol[middle].name;
@@ -675,8 +661,7 @@ Returns:      offset in list, or -1 if not found
 static int
 acl_checkcondition(uschar * name, condition_def * list, int end)
 {
-int start = 0;
-while (start < end)
+for (int start = 0; start < end; )
   {
   int mid = (start + end)/2;
   int c = Ustrcmp(name, list[mid].name);
@@ -705,9 +690,7 @@ Returns:      offset in list, or -1 if not found
 static int
 acl_checkname(uschar *name, uschar **list, int end)
 {
-int start = 0;
-
-while (start < end)
+for (int start = 0; start < end; )
   {
   int mid = (start + end)/2;
   int c = Ustrcmp(name, list[mid]);
@@ -745,7 +728,7 @@ acl_block **lastp = &yield;
 acl_block *this = NULL;
 acl_condition_block *cond;
 acl_condition_block **condp = NULL;
-uschar *s;
+uschar * s;
 
 *error = NULL;
 
@@ -777,7 +760,7 @@ while ((s = (*func)()) != NULL)
 
   if ((v = acl_checkname(name, verbs, nelem(verbs))) < 0)
     {
-    if (this == NULL)
+    if (!this)
       {
       *error = string_sprintf("unknown ACL verb \"%s\" in \"%s\"", name,
         saveline);
@@ -798,8 +781,10 @@ while ((s = (*func)()) != NULL)
     *lastp = this;
     lastp = &(this->next);
     this->next = NULL;
-    this->verb = v;
     this->condition = NULL;
+    this->verb = v;
+    this->srcline = config_lineno;     /* for debug output */
+    this->srcfile = config_filename;   /**/
     condp = &(this->condition);
     if (*s == 0) continue;               /* No condition on this line */
     if (*s == '!')
@@ -1057,9 +1042,8 @@ uschar *
 fn_hdrs_added(void)
 {
 gstring * g = NULL;
-header_line * h;
 
-for (h = acl_added_headers; h; h = h->next)
+for (header_line * h = acl_added_headers; h; h = h->next)
   {
   int i = h->slen;
   if (h->text[i-1] == '\n') i--;
@@ -1134,10 +1118,10 @@ if (log_message != NULL && log_message != user_message)
   /* Search previously logged warnings. They are kept in malloc
   store so they can be freed at the start of a new message. */
 
-  for (logged = acl_warn_logged; logged != NULL; logged = logged->next)
+  for (logged = acl_warn_logged; logged; logged = logged->next)
     if (Ustrcmp(logged->text, text) == 0) break;
 
-  if (logged == NULL)
+  if (!logged)
     {
     int length = Ustrlen(text) + 1;
     log_write(0, LOG_MAIN, "%s", text);
@@ -1151,7 +1135,7 @@ if (log_message != NULL && log_message != user_message)
 
 /* If there's no user message, we are done. */
 
-if (user_message == NULL) return;
+if (!user_message) return;
 
 /* If this isn't a message ACL, we can't do anything with a user message.
 Log an error. */
@@ -1216,11 +1200,10 @@ HDEBUG(D_acl)
 
 if ((rc = host_name_lookup()) != OK)
   {
-  *log_msgptr = (rc == DEFER)?
-    US"host lookup deferred for reverse lookup check"
-    :
-    string_sprintf("host lookup failed for reverse lookup check%s",
-      host_lookup_msg);
+  *log_msgptr = rc == DEFER
+    ? US"host lookup deferred for reverse lookup check"
+    : string_sprintf("host lookup failed for reverse lookup check%s",
+       host_lookup_msg);
   return rc;    /* DEFER or FAIL */
   }
 
@@ -1258,13 +1241,10 @@ static int
 acl_verify_csa_address(dns_answer *dnsa, dns_scan *dnss, int reset,
                        uschar *target)
 {
-dns_record *rr;
-dns_address *da;
+int rc = CSA_FAIL_NOADDR;
 
-BOOL target_found = FALSE;
-
-for (rr = dns_next_rr(dnsa, dnss, reset);
-     rr != NULL;
+for (dns_record * rr = dns_next_rr(dnsa, dnss, reset);
+     rr;
      rr = dns_next_rr(dnsa, dnss, RESET_NEXT))
   {
   /* Check this is an address RR for the target hostname. */
@@ -1277,12 +1257,12 @@ for (rr = dns_next_rr(dnsa, dnss, reset);
 
   if (strcmpic(target, rr->name) != 0) continue;
 
-  target_found = TRUE;
+  rc = CSA_FAIL_MISMATCH;
 
   /* Turn the target address RR into a list of textual IP addresses and scan
   the list. There may be more than one if it is an A6 RR. */
 
-  for (da = dns_address_from_rr(dnsa, rr); da != NULL; da = da->next)
+  for (dns_address * da = dns_address_from_rr(dnsa, rr); da; da = da->next)
     {
     /* If the client IP address matches the target IP address, it's good! */
 
@@ -1296,8 +1276,7 @@ for (rr = dns_next_rr(dnsa, dnss, reset);
 using an unauthorized IP address, otherwise the target has no authorized IP
 addresses. */
 
-if (target_found) return CSA_FAIL_MISMATCH;
-else return CSA_FAIL_NOADDR;
+return rc;
 }
 
 
@@ -1456,7 +1435,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
 
 /* If we didn't break the loop then no appropriate records were found. */
 
-if (rr == NULL) return t->data.val = CSA_UNKNOWN;
+if (!rr) return t->data.val = CSA_UNKNOWN;
 
 /* Do not check addresses if the target is ".", in accordance with RFC 2782.
 A target of "." indicates there are no valid addresses, so the client cannot
@@ -1533,7 +1512,7 @@ static verify_type_t verify_type_list[] = {
     { US"helo",                        VERIFY_HELO,            ~0,     TRUE,  0 },
     { US"csa",                 VERIFY_CSA,             ~0,     FALSE, 0 },
     { US"header_syntax",       VERIFY_HDR_SYNTAX,      ACL_BIT_DATA | ACL_BIT_NOTSMTP, TRUE, 0 },
-    { US"not_blind",           VERIFY_NOT_BLIND,       ACL_BIT_DATA | ACL_BIT_NOTSMTP, TRUE, 0 },
+    { US"not_blind",           VERIFY_NOT_BLIND,       ACL_BIT_DATA | ACL_BIT_NOTSMTP, FALSE, 0 },
     { US"header_sender",       VERIFY_HDR_SNDR,        ACL_BIT_DATA | ACL_BIT_NOTSMTP, FALSE, 0 },
     { US"sender",              VERIFY_SNDR,            ACL_BIT_MAIL | ACL_BIT_RCPT
                        |ACL_BIT_PREDATA | ACL_BIT_DATA | ACL_BIT_NOTSMTP,
@@ -1629,7 +1608,7 @@ if (!ss) goto BAD_VERIFY;
 
 /* Handle name/address consistency verification in a separate function. */
 
-for (vp= verify_type_list;
+for (vp = verify_type_list;
      CS vp < CS verify_type_list + sizeof(verify_type_list);
      vp++
     )
@@ -1732,14 +1711,27 @@ switch(vp->value)
   case VERIFY_NOT_BLIND:
     /* Check that no recipient of this message is "blind", that is, every envelope
     recipient must be mentioned in either To: or Cc:. */
+    {
+    BOOL case_sensitive = TRUE;
+
+    while ((ss = string_nextinlist(&list, &sep, NULL, 0)))
+      if (strcmpic(ss, US"case_insensitive") == 0)
+        case_sensitive = FALSE;
+      else
+        {
+        *log_msgptr = string_sprintf("unknown option \"%s\" in ACL "
+           "condition \"verify %s\"", ss, arg);
+        return ERROR;
+        }
 
-    if ((rc = verify_check_notblind()) != OK)
+    if ((rc = verify_check_notblind(case_sensitive)) != OK)
       {
       *log_msgptr = string_sprintf("bcc recipient detected");
       if (smtp_return_error_details)
         *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
       }
     return rc;
+    }
 
   /* The remaining verification tests check recipient and sender addresses,
   either from the envelope or from the header. There are a number of
@@ -1775,8 +1767,7 @@ switch(vp->value)
 /* Remaining items are optional; they apply to sender and recipient
 verification, including "header sender" verification. */
 
-while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
-      != NULL)
+while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)))
   {
   if (strcmpic(ss, US"defer_ok") == 0) defer_ok = TRUE;
   else if (strcmpic(ss, US"no_details") == 0) no_details = TRUE;
@@ -1809,10 +1800,10 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
         {
        const uschar * sublist = ss;
         int optsep = ',';
-        uschar *opt;
         uschar buffer[256];
-        while (isspace(*sublist)) sublist++;
+       uschar * opt;
 
+        while (isspace(*sublist)) sublist++;
         while ((opt = string_nextinlist(&sublist, &optsep, buffer, sizeof(buffer))))
           {
          callout_opt_t * op;
@@ -2415,7 +2406,7 @@ if ((t = tree_search(*anchor, key)))
 /* We aren't using a pre-computed rate, so get a previously recorded rate
 from the database, which will be updated and written back if required. */
 
-if (!(dbm = dbfn_open(US"ratelimit", O_RDWR, &dbblock, TRUE)))
+if (!(dbm = dbfn_open(US"ratelimit", O_RDWR, &dbblock, TRUE, TRUE)))
   {
   store_pool = old_pool;
   sender_rate = NULL;
@@ -3144,7 +3135,7 @@ for (; cb; cb = cb->next)
        if (*p == '/')
          {
          const uschar *pp = p + 1;
-         while (*pp != 0) pp++;
+         while (*pp) pp++;
          fake_response_text = expand_string(string_copyn(p+1, pp-p-1));
          p = pp;
          }
@@ -3177,11 +3168,6 @@ for (; cb; cb = cb->next)
        cancel_cutthrough_connection(TRUE, US"queueing forced");
        break;
 
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
-       case CONTROL_REQUIRETLS:
-       tls_requiretls |= REQUIRETLS_MSG;
-       break;
-#endif
        case CONTROL_SUBMISSION:
        originator_name = US"";
        f.submission_mode = TRUE;
@@ -3196,7 +3182,7 @@ for (; cb; cb = cb->next)
          else if (Ustrncmp(p, "/domain=", 8) == 0)
            {
            const uschar *pp = p + 8;
-           while (*pp != 0 && *pp != '/') pp++;
+           while (*pp && *pp != '/') pp++;
            submission_domain = string_copyn(p+8, pp-p-8);
            p = pp;
            }
@@ -3205,7 +3191,7 @@ for (; cb; cb = cb->next)
          else if (Ustrncmp(p, "/name=", 6) == 0)
            {
            const uschar *pp = p + 6;
-           while (*pp != 0) pp++;
+           while (*pp) pp++;
            submission_name = string_copy(parse_fix_phrase(p+6, pp-p-6,
              big_buffer, big_buffer_size));
            p = pp;
@@ -3521,7 +3507,7 @@ for (; cb; cb = cb->next)
       int logbits = 0;
       int sep = 0;
       const uschar *s = arg;
-      uschar *ss;
+      uschar * ss;
       while ((ss = string_nextinlist(&s, &sep, big_buffer, big_buffer_size)))
         {
         if (Ustrcmp(ss, "main") == 0) logbits |= LOG_MAIN;
@@ -3575,8 +3561,8 @@ for (; cb; cb = cb->next)
       {
       /* Separate the regular expression and any optional parameters. */
       const uschar * list = arg;
-      uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size);
-      uschar *opt;
+      uschar * ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size);
+      uschar * opt;
       BOOL defer_ok = FALSE;
       int timeout = 0;
 
@@ -3851,7 +3837,7 @@ for(;;)
   if (*acl_text == 0) return NULL;         /* No more data */
   yield = acl_text;                        /* Potential data line */
 
-  while (*acl_text != 0 && *acl_text != '\n') acl_text++;
+  while (*acl_text && *acl_text != '\n') acl_text++;
 
   /* If we hit the end before a newline, we have the whole logical line. If
   it's a comment, there's no more data to be given. Otherwise, yield it. */
@@ -3994,11 +3980,10 @@ read an ACL from a file, and save it so it can be re-used. */
 
 if (Ustrchr(ss, ' ') == NULL)
   {
-  tree_node *t = tree_search(acl_anchor, ss);
-  if (t != NULL)
+  tree_node * t = tree_search(acl_anchor, ss);
+  if (t)
     {
-    acl = (acl_block *)(t->data.ptr);
-    if (acl == NULL)
+    if (!(acl = (acl_block *)(t->data.ptr)))
       {
       HDEBUG(D_acl) debug_printf_indent("ACL \"%s\" is empty: implicit DENY\n", ss);
       return FAIL;
@@ -4010,8 +3995,7 @@ if (Ustrchr(ss, ' ') == NULL)
   else if (*ss == '/')
     {
     struct stat statbuf;
-    fd = Uopen(ss, O_RDONLY, 0);
-    if (fd < 0)
+    if ((fd = Uopen(ss, O_RDONLY, 0)) < 0)
       {
       *log_msgptr = string_sprintf("failed to open ACL file \"%s\": %s", ss,
         strerror(errno));
@@ -4046,13 +4030,13 @@ if (Ustrchr(ss, ' ') == NULL)
 in the ACL tree, having read it into the POOL_PERM store pool so that it
 persists between multiple messages. */
 
-if (acl == NULL)
+if (!acl)
   {
   int old_pool = store_pool;
   if (fd >= 0) store_pool = POOL_PERM;
   acl = acl_read(acl_getline, log_msgptr);
   store_pool = old_pool;
-  if (acl == NULL && *log_msgptr != NULL) return ERROR;
+  if (!acl && *log_msgptr) return ERROR;
   if (fd >= 0)
     {
     tree_node *t = store_get_perm(sizeof(tree_node) + Ustrlen(ss));
@@ -4064,7 +4048,7 @@ if (acl == NULL)
 
 /* Now we have an ACL to use. It's possible it may be NULL. */
 
-while (acl != NULL)
+while (acl)
   {
   int cond;
   int basic_errno = 0;
@@ -4075,7 +4059,8 @@ while (acl != NULL)
   *log_msgptr = *user_msgptr = NULL;
   f.acl_temp_details = FALSE;
 
-  HDEBUG(D_acl) debug_printf_indent("processing \"%s\"\n", verbs[acl->verb]);
+  HDEBUG(D_acl) debug_printf_indent("processing \"%s\" (%s %d)\n",
+    verbs[acl->verb], acl->srcfile, acl->srcline);
 
   /* Clear out any search error message from a previous check before testing
   this condition. */
@@ -4090,44 +4075,47 @@ while (acl != NULL)
   switch (cond)
     {
     case DEFER:
-    HDEBUG(D_acl) debug_printf_indent("%s: condition test deferred in %s\n", verbs[acl->verb], acl_name);
-    if (basic_errno != ERRNO_CALLOUTDEFER)
-      {
-      if (search_error_message != NULL && *search_error_message != 0)
-        *log_msgptr = search_error_message;
-      if (smtp_return_error_details) f.acl_temp_details = TRUE;
-      }
-    else
-      f.acl_temp_details = TRUE;
-    if (acl->verb != ACL_WARN) return DEFER;
-    break;
+      HDEBUG(D_acl) debug_printf_indent("%s: condition test deferred in %s\n",
+       verbs[acl->verb], acl_name);
+      if (basic_errno != ERRNO_CALLOUTDEFER)
+       {
+       if (search_error_message != NULL && *search_error_message != 0)
+         *log_msgptr = search_error_message;
+       if (smtp_return_error_details) f.acl_temp_details = TRUE;
+       }
+      else
+       f.acl_temp_details = TRUE;
+      if (acl->verb != ACL_WARN) return DEFER;
+      break;
 
     default:      /* Paranoia */
     case ERROR:
-    HDEBUG(D_acl) debug_printf_indent("%s: condition test error in %s\n", verbs[acl->verb], acl_name);
-    return ERROR;
+      HDEBUG(D_acl) debug_printf_indent("%s: condition test error in %s\n",
+       verbs[acl->verb], acl_name);
+      return ERROR;
 
     case OK:
-    HDEBUG(D_acl) debug_printf_indent("%s: condition test succeeded in %s\n",
-      verbs[acl->verb], acl_name);
-    break;
+      HDEBUG(D_acl) debug_printf_indent("%s: condition test succeeded in %s\n",
+       verbs[acl->verb], acl_name);
+      break;
 
     case FAIL:
-    HDEBUG(D_acl) debug_printf_indent("%s: condition test failed in %s\n", verbs[acl->verb], acl_name);
-    break;
+      HDEBUG(D_acl) debug_printf_indent("%s: condition test failed in %s\n",
+       verbs[acl->verb], acl_name);
+      break;
 
     /* DISCARD and DROP can happen only from a nested ACL condition, and
     DISCARD can happen only for an "accept" or "discard" verb. */
 
     case DISCARD:
-    HDEBUG(D_acl) debug_printf_indent("%s: condition test yielded \"discard\" in %s\n",
-      verbs[acl->verb], acl_name);
-    break;
+      HDEBUG(D_acl) debug_printf_indent("%s: condition test yielded \"discard\" in %s\n",
+       verbs[acl->verb], acl_name);
+      break;
 
     case FAIL_DROP:
-    HDEBUG(D_acl) debug_printf_indent("%s: condition test yielded \"drop\" in %s\n",
-      verbs[acl->verb], acl_name);
-    break;
+      HDEBUG(D_acl) debug_printf_indent("%s: condition test yielded \"drop\" in %s\n",
+       verbs[acl->verb], acl_name);
+      break;
     }
 
   /* At this point, cond for most verbs is either OK or FAIL or (as a result of
@@ -4137,84 +4125,85 @@ while (acl != NULL)
   switch(acl->verb)
     {
     case ACL_ACCEPT:
-    if (cond == OK || cond == DISCARD)
-      {
-      HDEBUG(D_acl) debug_printf_indent("end of %s: ACCEPT\n", acl_name);
-      return cond;
-      }
-    if (endpass_seen)
-      {
-      HDEBUG(D_acl) debug_printf_indent("accept: endpass encountered - denying access\n");
-      return cond;
-      }
-    break;
+      if (cond == OK || cond == DISCARD)
+       {
+       HDEBUG(D_acl) debug_printf_indent("end of %s: ACCEPT\n", acl_name);
+       return cond;
+       }
+      if (endpass_seen)
+       {
+       HDEBUG(D_acl) debug_printf_indent("accept: endpass encountered - denying access\n");
+       return cond;
+       }
+      break;
 
     case ACL_DEFER:
-    if (cond == OK)
-      {
-      HDEBUG(D_acl) debug_printf_indent("end of %s: DEFER\n", acl_name);
-      if (acl_quit_check) goto badquit;
-      f.acl_temp_details = TRUE;
-      return DEFER;
-      }
-    break;
+      if (cond == OK)
+       {
+       HDEBUG(D_acl) debug_printf_indent("end of %s: DEFER\n", acl_name);
+       if (acl_quit_check) goto badquit;
+       f.acl_temp_details = TRUE;
+       return DEFER;
+       }
+      break;
 
     case ACL_DENY:
-    if (cond == OK)
-      {
-      HDEBUG(D_acl) debug_printf_indent("end of %s: DENY\n", acl_name);
-      if (acl_quit_check) goto badquit;
-      return FAIL;
-      }
-    break;
+      if (cond == OK)
+       {
+       HDEBUG(D_acl) debug_printf_indent("end of %s: DENY\n", acl_name);
+       if (acl_quit_check) goto badquit;
+       return FAIL;
+       }
+      break;
 
     case ACL_DISCARD:
-    if (cond == OK || cond == DISCARD)
-      {
-      HDEBUG(D_acl) debug_printf_indent("end of %s: DISCARD\n", acl_name);
-      if (acl_quit_check) goto badquit;
-      return DISCARD;
-      }
-    if (endpass_seen)
-      {
-      HDEBUG(D_acl) debug_printf_indent("discard: endpass encountered - denying access\n");
-      return cond;
-      }
-    break;
+      if (cond == OK || cond == DISCARD)
+       {
+       HDEBUG(D_acl) debug_printf_indent("end of %s: DISCARD\n", acl_name);
+       if (acl_quit_check) goto badquit;
+       return DISCARD;
+       }
+      if (endpass_seen)
+       {
+       HDEBUG(D_acl)
+         debug_printf_indent("discard: endpass encountered - denying access\n");
+       return cond;
+       }
+      break;
 
     case ACL_DROP:
-    if (cond == OK)
-      {
-      HDEBUG(D_acl) debug_printf_indent("end of %s: DROP\n", acl_name);
-      if (acl_quit_check) goto badquit;
-      return FAIL_DROP;
-      }
-    break;
+      if (cond == OK)
+       {
+       HDEBUG(D_acl) debug_printf_indent("end of %s: DROP\n", acl_name);
+       if (acl_quit_check) goto badquit;
+       return FAIL_DROP;
+       }
+      break;
 
     case ACL_REQUIRE:
-    if (cond != OK)
-      {
-      HDEBUG(D_acl) debug_printf_indent("end of %s: not OK\n", acl_name);
-      if (acl_quit_check) goto badquit;
-      return cond;
-      }
-    break;
+      if (cond != OK)
+       {
+       HDEBUG(D_acl) debug_printf_indent("end of %s: not OK\n", acl_name);
+       if (acl_quit_check) goto badquit;
+       return cond;
+       }
+      break;
 
     case ACL_WARN:
-    if (cond == OK)
-      acl_warn(where, *user_msgptr, *log_msgptr);
-    else if (cond == DEFER && LOGGING(acl_warn_skipped))
-      log_write(0, LOG_MAIN, "%s Warning: ACL \"warn\" statement skipped: "
-        "condition test deferred%s%s", host_and_ident(TRUE),
-        (*log_msgptr == NULL)? US"" : US": ",
-        (*log_msgptr == NULL)? US"" : *log_msgptr);
-    *log_msgptr = *user_msgptr = NULL;  /* In case implicit DENY follows */
-    break;
+      if (cond == OK)
+       acl_warn(where, *user_msgptr, *log_msgptr);
+      else if (cond == DEFER && LOGGING(acl_warn_skipped))
+       log_write(0, LOG_MAIN, "%s Warning: ACL \"warn\" statement skipped: "
+         "condition test deferred%s%s", host_and_ident(TRUE),
+         (*log_msgptr == NULL)? US"" : US": ",
+         (*log_msgptr == NULL)? US"" : *log_msgptr);
+      *log_msgptr = *user_msgptr = NULL;  /* In case implicit DENY follows */
+      break;
 
     default:
-    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "internal ACL error: unknown verb %d",
-      acl->verb);
-    break;
+      log_write(0, LOG_MAIN|LOG_PANIC_DIE, "internal ACL error: unknown verb %d",
+       acl->verb);
+      break;
     }
 
   /* Pass to the next ACL item */