X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/d7bed7717e93c472282ed0e555fa64e0785d0172..dd7b74e90a96eaf109796d8f9499578571a1572c:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index a1d1915fb..1ac2bee23 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; + +/* 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 }, -/* Flags to identify the modifiers */ + { US"add_header", TRUE, TRUE, + (unsigned int) + ~((1<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++; @@ -1421,7 +1283,6 @@ acl_verify_csa(const uschar *domain) { tree_node *t; const uschar *found; -uschar *p; int priority, weight, port; dns_answer dnsa; dns_scan dnss; @@ -1499,14 +1360,13 @@ switch (dns_special_lookup(&dnsa, domain, T_CSA, &found)) /* Scan the reply for well-formed CSA SRV records. */ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr != NULL; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) + rr; + rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == T_SRV) { - if (rr->type != T_SRV) continue; + const uschar * p = rr->data; /* Extract the numerical SRV fields (p is incremented) */ - p = rr->data; GETSHORT(priority, p); GETSHORT(weight, p); GETSHORT(port, p); @@ -1525,12 +1385,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); SRV records of their own. */ if (Ustrcmp(found, domain) != 0) - { - if (port & 1) - return t->data.val = CSA_FAIL_EXPLICIT; - else - return t->data.val = CSA_UNKNOWN; - } + return t->data.val = port & 1 ? CSA_FAIL_EXPLICIT : CSA_UNKNOWN; /* This CSA SRV record refers directly to our domain, so we check the value in the weight field to work out the domain's authorization. 0 and 1 are @@ -2834,17 +2689,17 @@ uschar * errstr; hostname = string_nextinlist(&arg, &sep, NULL, 0); portstr = string_nextinlist(&arg, &sep, NULL, 0); -if (hostname == NULL) +if (!hostname) { *log_msgptr = US"missing destination host in \"udpsend\" modifier"; return ERROR; } -if (portstr == NULL) +if (!portstr) { *log_msgptr = US"missing destination port in \"udpsend\" modifier"; return ERROR; } -if (arg == NULL) +if (!arg) { *log_msgptr = US"missing datagram payload in \"udpsend\" modifier"; return ERROR; @@ -2983,7 +2838,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 +2857,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 +2875,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 +3637,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 */ }