Return remote errors for LMTP over pipe (so now it's the same as LMTP
[exim.git] / src / src / acl.c
index 8c2ab699a11982f94af7412351d0a80603c62d36..8274e0c73f00704467b8d985284ecb25ce82d736 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.64 2006/09/19 11:28:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.66 2006/09/25 10:14:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -65,6 +65,7 @@ enum { ACLC_ACL,
        ACLC_HOSTS,
        ACLC_LOCAL_PARTS,
        ACLC_LOG_MESSAGE,
+       ACLC_LOG_REJECT_TARGET,
        ACLC_LOGWRITE,
 #ifdef WITH_CONTENT_SCAN
        ACLC_MALWARE,
@@ -90,8 +91,9 @@ enum { ACLC_ACL,
        ACLC_VERIFY };
 
 /* ACL conditions/modifiers: "delay", "control", "endpass", "message",
-"log_message", "logwrite", and "set" are modifiers that look like conditions
-but always return TRUE. They are used for their side effects. */
+"log_message", "log_reject_target", "logwrite", and "set" are modifiers that
+look like conditions but always return TRUE. They are used for their side
+effects. */
 
 static uschar *conditions[] = {
   US"acl",
@@ -117,8 +119,15 @@ static uschar *conditions[] = {
   US"dk_senders",
   US"dk_status",
 #endif
-  US"dnslists", US"domains", US"encrypted",
-  US"endpass", US"hosts", US"local_parts", US"log_message", US"logwrite",
+  US"dnslists",
+  US"domains",
+  US"encrypted",
+  US"endpass",
+  US"hosts",
+  US"local_parts",
+  US"log_message",
+  US"log_reject_target",
+  US"logwrite",
 #ifdef WITH_CONTENT_SCAN
   US"malware",
 #endif
@@ -232,6 +241,7 @@ static uschar cond_expand_at_top[] = {
   FALSE,   /* hosts */
   FALSE,   /* local_parts */
   TRUE,    /* log_message */
+  TRUE,    /* log_reject_target */
   TRUE,    /* logwrite */
 #ifdef WITH_CONTENT_SCAN
   TRUE,    /* malware */
@@ -290,6 +300,7 @@ static uschar cond_modifiers[] = {
   FALSE,   /* hosts */
   FALSE,   /* local_parts */
   TRUE,    /* log_message */
+  TRUE,    /* log_reject_target */
   TRUE,    /* logwrite */
 #ifdef WITH_CONTENT_SCAN
   FALSE,   /* malware */
@@ -433,6 +444,8 @@ static unsigned int cond_forbids[] = {
 
   0,                                               /* log_message */
 
+  0,                                               /* log_reject_target */
+
   0,                                               /* logwrite */
 
   #ifdef WITH_CONTENT_SCAN
@@ -808,8 +821,10 @@ while ((s = (*func)()) != NULL)
   gives us a variable name to insert into the data block. The original ACL
   variable names were acl_c0 ... acl_c9 and acl_m0 ... acl_m9. This was
   extended to 20 of each type, but after that people successfully argued for
-  arbitrary names. For compatibility, however, the names must still start with
-  acl_c or acl_m. After that, we allow alphanumerics and underscores. */
+  arbitrary names. In the new scheme, the names must start with acl_c or acl_m.
+  After that, we allow alphanumerics and underscores, but the first character
+  after c or m must be a digit or an underscore. This retains backwards
+  compatibility. */
 
   if (c == ACLC_SET)
     {
@@ -824,6 +839,14 @@ while ((s = (*func)()) != NULL)
       }
 
     endptr = s + 5;
+    if (!isdigit(*endptr) && *endptr != '_')
+      {
+      *error = string_sprintf("invalid variable name after \"set\" in ACL "
+        "modifier \"set %s\" (digit or underscore must follow acl_c or acl_m)",
+        s);
+      return NULL;
+      }
+
     while (*endptr != 0 && *endptr != '=' && !isspace(*endptr))
       {
       if (!isalnum(*endptr) && *endptr != '_')
@@ -835,13 +858,6 @@ while ((s = (*func)()) != NULL)
       endptr++;
       }
 
-    if (endptr - s < 6)
-      {
-      *error = string_sprintf("invalid variable name after \"set\" in ACL "
-        "modifier \"set %s\" (must be at least 6 characters)", s);
-      return NULL;
-      }
-
     cond->u.varname = string_copyn(s + 4, endptr - s - 4);
     s = endptr;
     while (isspace(*s)) s++;
@@ -2841,6 +2857,29 @@ for (; cb != NULL; cb = cb->next)
       &deliver_localpart_data);
     break;
 
+    case ACLC_LOG_REJECT_TARGET:
+      {
+      int logbits = 0;
+      int sep = 0;
+      uschar *s = arg;
+      uschar *ss;
+      while ((ss = string_nextinlist(&s, &sep, big_buffer, big_buffer_size))
+              != NULL)
+        {
+        if (Ustrcmp(ss, "main") == 0) logbits |= LOG_MAIN;
+        else if (Ustrcmp(ss, "panic") == 0) logbits |= LOG_PANIC;
+        else if (Ustrcmp(ss, "reject") == 0) logbits |= LOG_REJECT;
+        else
+          {
+          logbits |= LOG_MAIN|LOG_REJECT;
+          log_write(0, LOG_MAIN|LOG_PANIC, "unknown log name \"%s\" in "
+            "\"log_reject_target\" in %s ACL", ss, acl_wherenames[where]);
+          }
+        }
+      log_reject_target = logbits;
+      }
+    break;
+
     case ACLC_LOGWRITE:
       {
       int logbits = 0;
@@ -2867,6 +2906,8 @@ for (; cb != NULL; cb = cb->next)
         s++;
         }
       while (isspace(*s)) s++;
+
+
       if (logbits == 0) logbits = LOG_MAIN;
       log_write(0, logbits, "%s", string_printing(s));
       }
@@ -2875,7 +2916,7 @@ for (; cb != NULL; cb = cb->next)
     #ifdef WITH_CONTENT_SCAN
     case ACLC_MALWARE:
       {
-      /* Seperate the regular expression and any optional parameters. */
+      /* Separate the regular expression and any optional parameters. */
       uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size);
       /* Run the malware backend. */
       rc = malware(&ss);
@@ -3510,6 +3551,7 @@ address_item *addr = NULL;
 *user_msgptr = *log_msgptr = NULL;
 sender_verified_failed = NULL;
 ratelimiters_cmd = NULL;
+log_reject_target = LOG_MAIN|LOG_REJECT;
 
 if (where == ACL_WHERE_RCPT)
   {