summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2016-09-18 22:47:22 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2016-09-18 22:58:51 +0100
commit2d009132e2de39646108f9c5a829f0611735e730 (patch)
tree8f9037d9e5c5b8a11cb82e698b91bfc5df177412
parentd7bed7717e93c472282ed0e555fa64e0785d0172 (diff)
downloadexim4-2d009132e2de39646108f9c5a829f0611735e730.tar.gz
ACL: merge the tables used for codition/modifier decode
-rw-r--r--doc/doc-txt/ChangeLog3
-rw-r--r--src/scripts/source_checks2
-rw-r--r--src/src/acl.c620
3 files changed, 243 insertions, 382 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index a29974070..f2000b5d4 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -91,7 +91,8 @@ JH/23 Bug 1874: fix continued use of a connection for further deliveries.
JH/24 Bug 1832: Log EHLO response on getting conn-close response for HELO.
JH/25 Decoding ACL controls is now done using a binary search; the sourcecode
- takes up less space and should be simpler to maintain.
+ takes up less space and should be simpler to maintain. Merge the ACL
+ condition decode tables also, with similar effect.
Exim version 4.87
diff --git a/src/scripts/source_checks b/src/scripts/source_checks
index 86aff13b1..6da8a8664 100644
--- a/src/scripts/source_checks
+++ b/src/scripts/source_checks
@@ -27,6 +27,7 @@ done <<-END
transports/pipe.c pipe_transport_options
transports/smtp.c smtp_transport_options
expand.c var_table
+ acl.c conditions
acl.c controls_list
END
@@ -46,6 +47,5 @@ done <<-END
expand.c op_table_main
expand.c cond_table
acl.c verbs
- acl.c conditions
END
diff --git a/src/src/acl.c b/src/src/acl.c
index a1d1915fb..fb2a7da4b 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -46,7 +46,7 @@ static int msgcond[] = {
};
/* ACL condition and modifier codes - keep in step with the table that
-follows, and the cond_expand_at_top and uschar cond_modifiers tables lower
+follows.
down. */
enum { ACLC_ACL,
@@ -113,402 +113,236 @@ enum { ACLC_ACL,
modifiers that look like conditions but always return TRUE. They are used for
their side effects. */
-static uschar *conditions[] = {
- US"acl",
- US"add_header",
- US"authenticated",
-#ifdef EXPERIMENTAL_BRIGHTMAIL
- US"bmi_optin",
-#endif
- US"condition",
- US"continue",
- US"control",
-#ifdef EXPERIMENTAL_DCC
- US"dcc",
-#endif
-#ifdef WITH_CONTENT_SCAN
- US"decode",
-#endif
- US"delay",
-#ifndef DISABLE_DKIM
- US"dkim_signers",
- US"dkim_status",
-#endif
-#ifdef EXPERIMENTAL_DMARC
- US"dmarc_status",
-#endif
- 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
- US"message",
-#ifdef WITH_CONTENT_SCAN
- US"mime_regex",
-#endif
- US"queue",
- US"ratelimit",
- US"recipients",
-#ifdef WITH_CONTENT_SCAN
- US"regex",
-#endif
- US"remove_header",
- US"sender_domains",
- US"senders",
- US"set",
-#ifdef WITH_CONTENT_SCAN
- US"spam",
-#endif
-#ifdef EXPERIMENTAL_SPF
- US"spf",
- US"spf_guess",
-#endif
- US"udpsend",
- US"verify" };
-
+typedef struct condition_def {
+ uschar *name;
-/* Flags to indicate for which conditions/modifiers a string expansion is done
+/* Flag to indicate the condition/modifier has a string expansion done
at the outer level. In the other cases, expansion already occurs in the
checking functions. */
+ BOOL expand_at_top:1;
-static uschar cond_expand_at_top[] = {
- FALSE, /* acl */
- TRUE, /* add_header */
- FALSE, /* authenticated */
-#ifdef EXPERIMENTAL_BRIGHTMAIL
- TRUE, /* bmi_optin */
-#endif
- TRUE, /* condition */
- TRUE, /* continue */
- TRUE, /* control */
-#ifdef EXPERIMENTAL_DCC
- TRUE, /* dcc */
-#endif
-#ifdef WITH_CONTENT_SCAN
- TRUE, /* decode */
-#endif
- TRUE, /* delay */
-#ifndef DISABLE_DKIM
- TRUE, /* dkim_signers */
- TRUE, /* dkim_status */
-#endif
-#ifdef EXPERIMENTAL_DMARC
- TRUE, /* dmarc_status */
-#endif
- TRUE, /* dnslists */
- FALSE, /* domains */
- FALSE, /* encrypted */
- TRUE, /* endpass */
- FALSE, /* hosts */
- FALSE, /* local_parts */
- TRUE, /* log_message */
- TRUE, /* log_reject_target */
- TRUE, /* logwrite */
-#ifdef WITH_CONTENT_SCAN
- TRUE, /* malware */
-#endif
- TRUE, /* message */
-#ifdef WITH_CONTENT_SCAN
- TRUE, /* mime_regex */
-#endif
- TRUE, /* queue */
- TRUE, /* ratelimit */
- FALSE, /* recipients */
-#ifdef WITH_CONTENT_SCAN
- TRUE, /* regex */
-#endif
- TRUE, /* remove_header */
- FALSE, /* sender_domains */
- FALSE, /* senders */
- TRUE, /* set */
-#ifdef WITH_CONTENT_SCAN
- TRUE, /* spam */
-#endif
-#ifdef EXPERIMENTAL_SPF
- TRUE, /* spf */
- TRUE, /* spf_guess */
-#endif
- TRUE, /* udpsend */
- TRUE /* verify */
-};
+ BOOL is_modifier:1;
-/* Flags to identify the modifiers */
+/* Bit map vector of which conditions and modifiers are not allowed at certain
+times. For each condition and modifier, there's a bitmap of dis-allowed times.
+For some, it is easier to specify the negation of a small number of allowed
+times. */
+ unsigned forbids;
+
+} condition_def;
+
+static condition_def conditions[] = {
+ { US"acl", FALSE, FALSE, 0 },
+
+ { US"add_header", TRUE, TRUE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)|
+ (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
+#ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+#endif
+ (1<<ACL_WHERE_MIME)|(1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_DKIM)|
+ (1<<ACL_WHERE_NOTSMTP_START)),
+ },
-static uschar cond_modifiers[] = {
- FALSE, /* acl */
- TRUE, /* add_header */
- FALSE, /* authenticated */
+ { US"authenticated", FALSE, FALSE,
+ (1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_NOTSMTP_START)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO),
+ },
#ifdef EXPERIMENTAL_BRIGHTMAIL
- TRUE, /* bmi_optin */
+ { US"bmi_optin", TRUE, TRUE,
+ (1<<ACL_WHERE_AUTH)|
+ (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_MIME)|
+# ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+# endif
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_MAILAUTH)|
+ (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
+ (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_NOTSMTP_START),
+ },
#endif
- FALSE, /* condition */
- TRUE, /* continue */
- TRUE, /* control */
+ { US"condition", TRUE, FALSE, 0 },
+ { US"continue", TRUE, TRUE, 0 },
+
+ /* Certain types of control are always allowed, so we let it through
+ always and check in the control processing itself. */
+ { US"control", TRUE, TRUE, 0 },
+
#ifdef EXPERIMENTAL_DCC
- FALSE, /* dcc */
+ { US"dcc", TRUE, FALSE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|
+# ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+# endif
+ (1<<ACL_WHERE_NOTSMTP)),
+ },
#endif
#ifdef WITH_CONTENT_SCAN
- FALSE, /* decode */
+ { US"decode", TRUE, FALSE, (unsigned int) ~(1<<ACL_WHERE_MIME) },
+
#endif
- TRUE, /* delay */
+ { US"delay", TRUE, TRUE, (1<<ACL_WHERE_NOTQUIT) },
#ifndef DISABLE_DKIM
- FALSE, /* dkim_signers */
- FALSE, /* dkim_status */
+ { US"dkim_signers", TRUE, FALSE, (unsigned int) ~(1<<ACL_WHERE_DKIM) },
+ { US"dkim_status", TRUE, FALSE, (unsigned int) ~(1<<ACL_WHERE_DKIM) },
#endif
#ifdef EXPERIMENTAL_DMARC
- FALSE, /* dmarc_status */
+ { US"dmarc_status", TRUE, FALSE, (unsigned int) ~(1<<ACL_WHERE_DATA) },
#endif
- FALSE, /* dnslists */
- FALSE, /* domains */
- FALSE, /* encrypted */
- TRUE, /* endpass */
- FALSE, /* hosts */
- FALSE, /* local_parts */
- TRUE, /* log_message */
- TRUE, /* log_reject_target */
- TRUE, /* logwrite */
-#ifdef WITH_CONTENT_SCAN
- FALSE, /* malware */
-#endif
- TRUE, /* message */
-#ifdef WITH_CONTENT_SCAN
- FALSE, /* mime_regex */
-#endif
- TRUE, /* queue */
- FALSE, /* ratelimit */
- FALSE, /* recipients */
-#ifdef WITH_CONTENT_SCAN
- FALSE, /* regex */
-#endif
- TRUE, /* remove_header */
- FALSE, /* sender_domains */
- FALSE, /* senders */
- TRUE, /* set */
-#ifdef WITH_CONTENT_SCAN
- FALSE, /* spam */
-#endif
-#ifdef EXPERIMENTAL_SPF
- FALSE, /* spf */
- FALSE, /* spf_guess */
-#endif
- TRUE, /* udpsend */
- FALSE /* verify */
-};
-/* Bit map vector of which conditions and modifiers are not allowed at certain
-times. For each condition and modifier, there's a bitmap of dis-allowed times.
-For some, it is easier to specify the negation of a small number of allowed
-times. */
-
-static unsigned int cond_forbids[] = {
- 0, /* acl */
-
- (unsigned int)
- ~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* add_header */
- (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_MIME)|(1<<ACL_WHERE_NOTSMTP)|
- (1<<ACL_WHERE_DKIM)|
- (1<<ACL_WHERE_NOTSMTP_START)),
-
- (1<<ACL_WHERE_NOTSMTP)| /* authenticated */
- (1<<ACL_WHERE_NOTSMTP_START)|
- (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO),
-
- #ifdef EXPERIMENTAL_BRIGHTMAIL
- (1<<ACL_WHERE_AUTH)| /* bmi_optin */
- (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_MIME)|
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_MAILAUTH)|
- (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_PREDATA)|
- (1<<ACL_WHERE_NOTSMTP_START),
- #endif
-
- 0, /* condition */
-
- 0, /* continue */
+ /* Explicit key lookups can be made in non-smtp ACLs so pass
+ always and check in the verify processing itself. */
+ { US"dnslists", TRUE, FALSE, 0 },
- /* Certain types of control are always allowed, so we let it through
- always and check in the control processing itself. */
+ { US"domains", FALSE, FALSE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_RCPT)
+ |(1<<ACL_WHERE_VRFY)
+#ifndef DISABLE_PRDR
+ |(1<<ACL_WHERE_PRDR)
+#endif
+ ),
+ },
+ { US"encrypted", FALSE, FALSE,
+ (1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_CONNECT)|
+ (1<<ACL_WHERE_NOTSMTP_START)|
+ (1<<ACL_WHERE_HELO),
+ },
- 0, /* control */
+ { US"endpass", TRUE, TRUE, 0 },
- #ifdef EXPERIMENTAL_DCC
- (unsigned int)
- ~((1<<ACL_WHERE_DATA)| /* dcc */
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_NOTSMTP)),
- #endif
+ { US"hosts", FALSE, FALSE,
+ (1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_NOTSMTP_START),
+ },
+ { US"local_parts", FALSE, FALSE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_RCPT)
+ |(1<<ACL_WHERE_VRFY)
+ #ifndef DISABLE_PRDR
+ |(1<<ACL_WHERE_PRDR)
+ #endif
+ ),
+ },
- #ifdef WITH_CONTENT_SCAN
- (unsigned int)
- ~(1<<ACL_WHERE_MIME), /* decode */
- #endif
+ { US"log_message", TRUE, TRUE, 0 },
+ { US"log_reject_target", TRUE, TRUE, 0 },
+ { US"logwrite", TRUE, TRUE, 0 },
- (1<<ACL_WHERE_NOTQUIT), /* delay */
+#ifdef WITH_CONTENT_SCAN
+ { US"malware", TRUE, FALSE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|
+# ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+# endif
+ (1<<ACL_WHERE_NOTSMTP)),
+ },
+#endif
- #ifndef DISABLE_DKIM
- (unsigned int)
- ~(1<<ACL_WHERE_DKIM), /* dkim_signers */
+ { US"message", TRUE, TRUE, 0 },
+#ifdef WITH_CONTENT_SCAN
+ { US"mime_regex", TRUE, FALSE, (unsigned int) ~(1<<ACL_WHERE_MIME) },
+#endif
- (unsigned int)
- ~(1<<ACL_WHERE_DKIM), /* dkim_status */
- #endif
+ { US"queue", TRUE, TRUE,
+ (1<<ACL_WHERE_NOTSMTP)|
+#ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+#endif
+ (1<<ACL_WHERE_DATA),
+ },
- #ifdef EXPERIMENTAL_DMARC
- (unsigned int)
- ~(1<<ACL_WHERE_DATA), /* dmarc_status */
- #endif
+ { US"ratelimit", TRUE, FALSE, 0 },
+ { US"recipients", FALSE, FALSE, (unsigned int) ~(1<<ACL_WHERE_RCPT) },
- /* Explicit key lookups can be made in non-smtp ACLs so pass
- always and check in the verify processing itself. */
+#ifdef WITH_CONTENT_SCAN
+ { US"regex", TRUE, FALSE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|
+# ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+# endif
+ (1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_MIME)),
+ },
- 0, /* dnslists */
-
- (unsigned int)
- ~((1<<ACL_WHERE_RCPT) /* domains */
- |(1<<ACL_WHERE_VRFY)
- #ifndef DISABLE_PRDR
- |(1<<ACL_WHERE_PRDR)
- #endif
- ),
-
- (1<<ACL_WHERE_NOTSMTP)| /* encrypted */
- (1<<ACL_WHERE_CONNECT)|
- (1<<ACL_WHERE_NOTSMTP_START)|
- (1<<ACL_WHERE_HELO),
-
- 0, /* endpass */
-
- (1<<ACL_WHERE_NOTSMTP)| /* hosts */
- (1<<ACL_WHERE_NOTSMTP_START),
-
- (unsigned int)
- ~((1<<ACL_WHERE_RCPT) /* local_parts */
- |(1<<ACL_WHERE_VRFY)
- #ifndef DISABLE_PRDR
- |(1<<ACL_WHERE_PRDR)
- #endif
- ),
-
- 0, /* log_message */
-
- 0, /* log_reject_target */
-
- 0, /* logwrite */
-
- #ifdef WITH_CONTENT_SCAN
- (unsigned int)
- ~((1<<ACL_WHERE_DATA)| /* malware */
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_NOTSMTP)),
- #endif
-
- 0, /* message */
-
- #ifdef WITH_CONTENT_SCAN
- (unsigned int)
- ~(1<<ACL_WHERE_MIME), /* mime_regex */
- #endif
-
- (1<<ACL_WHERE_NOTSMTP)| /* queue */
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_DATA),
-
- 0, /* ratelimit */
-
- (unsigned int)
- ~(1<<ACL_WHERE_RCPT), /* recipients */
-
- #ifdef WITH_CONTENT_SCAN
- (unsigned int)
- ~((1<<ACL_WHERE_DATA)| /* regex */
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_NOTSMTP)|
- (1<<ACL_WHERE_MIME)),
- #endif
-
- (unsigned int)
- ~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* remove_header */
- (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_MIME)|(1<<ACL_WHERE_NOTSMTP)|
- (1<<ACL_WHERE_NOTSMTP_START)),
-
- (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)| /* sender_domains */
- (1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY),
-
- (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)| /* senders */
- (1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY),
-
- 0, /* set */
-
- #ifdef WITH_CONTENT_SCAN
- (unsigned int)
- ~((1<<ACL_WHERE_DATA)| /* spam */
- #ifndef DISABLE_PRDR
- (1<<ACL_WHERE_PRDR)|
- #endif
- (1<<ACL_WHERE_NOTSMTP)),
- #endif
-
- #ifdef EXPERIMENTAL_SPF
- (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)| /* spf */
- (1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_MAILAUTH)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
- (1<<ACL_WHERE_NOTSMTP)|
- (1<<ACL_WHERE_NOTSMTP_START),
+#endif
+ { US"remove_header", TRUE, TRUE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)|
+ (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
+#ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+#endif
+ (1<<ACL_WHERE_MIME)|(1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_NOTSMTP_START)),
+ },
+ { US"sender_domains", FALSE, FALSE,
+ (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|
+ (1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY),
+ },
+ { US"senders", FALSE, FALSE,
+ (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|
+ (1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY),
+ },
- (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)| /* spf_guess */
- (1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_MAILAUTH)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
- (1<<ACL_WHERE_NOTSMTP)|
- (1<<ACL_WHERE_NOTSMTP_START),
- #endif
+ { US"set", TRUE, TRUE, 0 },
- 0, /* udpsend */
+#ifdef WITH_CONTENT_SCAN
+ { US"spam", TRUE, FALSE,
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|
+# ifndef DISABLE_PRDR
+ (1<<ACL_WHERE_PRDR)|
+# endif
+ (1<<ACL_WHERE_NOTSMTP)),
+ },
+#endif
+#ifdef EXPERIMENTAL_SPF
+ { US"spf", TRUE, FALSE,
+ (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|
+ (1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_MAILAUTH)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
+ (1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_NOTSMTP_START),
+ },
+ { US"spf_guess", TRUE, FALSE,
+ (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|
+ (1<<ACL_WHERE_HELO)|
+ (1<<ACL_WHERE_MAILAUTH)|
+ (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY)|
+ (1<<ACL_WHERE_NOTSMTP)|
+ (1<<ACL_WHERE_NOTSMTP_START),
+ },
+#endif
+ { US"udpsend", TRUE, TRUE, 0 },
/* Certain types of verify are always allowed, so we let it through
always and check in the verify function itself */
-
- 0 /* verify */
+ { US"verify", TRUE, FALSE,
+ 0
+ },
};
+
/* Return values from decode_control(); used as index so keep in step
with the controls_list table that follows! */
@@ -776,6 +610,36 @@ return -1;
/*************************************************
+* Pick out condition from list *
+*************************************************/
+
+/* Use a binary chop method
+
+Arguments:
+ name name to find
+ list list of conditions
+ end size of list
+
+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)
+ {
+ int mid = (start + end)/2;
+ int c = Ustrcmp(name, list[mid].name);
+ if (c == 0) return mid;
+ if (c < 0) end = mid;
+ else start = mid + 1;
+ }
+return -1;
+}
+
+
+/*************************************************
* Pick out name from list *
*************************************************/
@@ -862,8 +726,7 @@ while ((s = (*func)()) != NULL)
/* If a verb is unrecognized, it may be another condition or modifier that
continues the previous verb. */
- v = acl_checkname(name, verbs, sizeof(verbs)/sizeof(char *));
- if (v < 0)
+ if ((v = acl_checkname(name, verbs, nelem(verbs))) < 0)
{
if (this == NULL)
{
@@ -900,8 +763,7 @@ while ((s = (*func)()) != NULL)
/* Handle a condition or modifier. */
- c = acl_checkname(name, conditions, sizeof(conditions)/sizeof(char *));
- if (c < 0)
+ if ((c = acl_checkcondition(name, conditions, nelem(conditions))) < 0)
{
*error = string_sprintf("unknown ACL condition/modifier in \"%s\"",
saveline);
@@ -910,10 +772,10 @@ while ((s = (*func)()) != NULL)
/* The modifiers may not be negated */
- if (negated && cond_modifiers[c])
+ if (negated && conditions[c].is_modifier)
{
*error = string_sprintf("ACL error: negation is not allowed with "
- "\"%s\"", conditions[c]);
+ "\"%s\"", conditions[c].name);
return NULL;
}
@@ -924,7 +786,7 @@ while ((s = (*func)()) != NULL)
this->verb != ACL_DISCARD)
{
*error = string_sprintf("ACL error: \"%s\" is not allowed with \"%s\"",
- conditions[c], verbs[this->verb]);
+ conditions[c].name, verbs[this->verb]);
return NULL;
}
@@ -991,7 +853,7 @@ while ((s = (*func)()) != NULL)
if (*s++ != '=')
{
*error = string_sprintf("\"=\" missing after ACL \"%s\" %s", name,
- cond_modifiers[c]? US"modifier" : US"condition");
+ conditions[c].is_modifier ? US"modifier" : US"condition");
return NULL;
}
while (isspace(*s)) s++;
@@ -2983,7 +2845,7 @@ for (; cb != NULL; cb = cb->next)
of them, but not for all, because expansion happens down in some lower level
checking functions in some cases. */
- if (cond_expand_at_top[cb->type])
+ if (conditions[cb->type].expand_at_top)
{
arg = expand_string(cb->arg);
if (arg == NULL)
@@ -3002,8 +2864,8 @@ for (; cb != NULL; cb = cb->next)
{
int lhswidth = 0;
debug_printf("check %s%s %n",
- (!cond_modifiers[cb->type] && cb->u.negated)? "!":"",
- conditions[cb->type], &lhswidth);
+ (!conditions[cb->type].is_modifier && cb->u.negated)? "!":"",
+ conditions[cb->type].name, &lhswidth);
if (cb->type == ACLC_SET)
{
@@ -3020,11 +2882,11 @@ for (; cb != NULL; cb = cb->next)
/* Check that this condition makes sense at this time */
- if ((cond_forbids[cb->type] & (1 << where)) != 0)
+ if ((conditions[cb->type].forbids & (1 << where)) != 0)
{
*log_msgptr = string_sprintf("cannot %s %s condition in %s ACL",
- cond_modifiers[cb->type]? "use" : "test",
- conditions[cb->type], acl_wherenames[where]);
+ conditions[cb->type].is_modifier ? "use" : "test",
+ conditions[cb->type].name, acl_wherenames[where]);
return ERROR;
}
@@ -3782,11 +3644,9 @@ for (; cb != NULL; cb = cb->next)
/* If a condition was negated, invert OK/FAIL. */
- if (!cond_modifiers[cb->type] && cb->u.negated)
- {
+ if (!conditions[cb->type].is_modifier && cb->u.negated)
if (rc == OK) rc = FAIL;
- else if (rc == FAIL || rc == FAIL_DROP) rc = OK;
- }
+ else if (rc == FAIL || rc == FAIL_DROP) rc = OK;
if (rc != OK) break; /* Conditions loop */
}