X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/90fc3069076c77a9b7b9f8c1112f62ca280cc8bc..99ea1c866060c4ca655973128f06d41c8efe9a44:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index a8db4a75f..8274e0c73 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.59 2006/06/07 15:06:26 fanf2 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 */ @@ -323,12 +334,14 @@ static unsigned int cond_forbids[] = { 0, /* acl */ (unsigned int) - ~((1<= max) + while (*endptr != 0 && *endptr != '=' && !isspace(*endptr)) { - BAD_ACL_VAR: - *error = string_sprintf("syntax error or unrecognized name after " - "\"set\" in ACL modifier \"set %s\"", s); - return NULL; + if (!isalnum(*endptr) && *endptr != '_') + { + *error = string_sprintf("invalid character \"%c\" in variable name " + "in ACL modifier \"set %s\"", *endptr, s); + return NULL; + } + endptr++; } - cond->u.varnumber = n + offset; + cond->u.varname = string_copyn(s + 4, endptr - s - 4); s = endptr; while (isspace(*s)) s++; } @@ -2348,7 +2387,7 @@ acl_check_condition(int verb, acl_condition_block *cb, int where, { uschar *user_message = NULL; uschar *log_message = NULL; -uschar *p; +uschar *p = NULL; int rc = OK; #ifdef WITH_CONTENT_SCAN int sep = '/'; @@ -2411,11 +2450,8 @@ for (; cb != NULL; cb = cb->next) if (cb->type == ACLC_SET) { - int n = cb->u.varnumber; - int t = (n < ACL_CVARS)? 'c' : 'm'; - if (n >= ACL_CVARS) n -= ACL_CVARS; - debug_printf("acl_%c%d ", t, n); - lhswidth += 7; + debug_printf("acl_%s ", cb->u.varname); + lhswidth += 5 + Ustrlen(cb->u.varname); } debug_printf("= %s\n", cb->arg); @@ -2821,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; @@ -2847,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)); } @@ -2855,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); @@ -2911,8 +2972,8 @@ for (; cb != NULL; cb = cb->next) case ACLC_SET: { int old_pool = store_pool; - if (cb->u.varnumber < ACL_CVARS) store_pool = POOL_PERM; - acl_var[cb->u.varnumber] = string_copy(arg); + if (cb->u.varname[0] == 'c') store_pool = POOL_PERM; + acl_var_create(cb->u.varname)->data.ptr = string_copy(arg); store_pool = old_pool; } break; @@ -3490,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) { @@ -3582,4 +3644,64 @@ if (rc != OK && *user_msgptr != NULL && Ustrlen(*user_msgptr) > 75) return rc; } + + +/************************************************* +* Create ACL variable * +*************************************************/ + +/* Create an ACL variable or reuse an existing one. ACL variables are in a +binary tree (see tree.c) with acl_var_c and acl_var_m as root nodes. + +Argument: + name pointer to the variable's name, starting with c or m + +Returns the pointer to variable's tree node +*/ + +tree_node * +acl_var_create(uschar *name) +{ +tree_node *node, **root; +root = (name[0] == 'c')? &acl_var_c : &acl_var_m; +node = tree_search(*root, name); +if (node == NULL) + { + node = store_get(sizeof(tree_node) + Ustrlen(name)); + Ustrcpy(node->name, name); + (void)tree_insertnode(root, node); + } +node->data.ptr = NULL; +return node; +} + + + +/************************************************* +* Write an ACL variable in spool format * +*************************************************/ + +/* This function is used as a callback for tree_walk when writing variables to +the spool file. To retain spool file compatibility, what is written is -aclc or +-aclm followed by the rest of the name and the data length, space separated, +then the value itself, starting on a new line, and terminated by an additional +newline. When we had only numbered ACL variables, the first line might look +like this: "-aclc 5 20". Now it might be "-aclc foo 20" for the variable called +acl_cfoo. + +Arguments: + name of the variable + value of the variable + ctx FILE pointer (as a void pointer) + +Returns: nothing +*/ + +void +acl_var_write(uschar *name, uschar *value, void *ctx) +{ +FILE *f = (FILE *)ctx; +fprintf(f, "-acl%c %s %d\n%s\n", name[0], name+1, Ustrlen(value), value); +} + /* End of acl.c */