-/* $Cambridge: exim/src/src/acl.c,v 1.50 2005/10/03 13:25:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.56 2006/03/02 12:25:48 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for handling Access Control Lists (ACLs) */
that follows! */
enum {
-#ifdef EXPERIMENTAL_BRIGHTMAIL
+ CONTROL_AUTH_UNADVERTISED,
+ #ifdef EXPERIMENTAL_BRIGHTMAIL
CONTROL_BMI_RUN,
-#endif
-#ifdef EXPERIMENTAL_DOMAINKEYS
+ #endif
+ #ifdef EXPERIMENTAL_DOMAINKEYS
CONTROL_DK_VERIFY,
-#endif
- CONTROL_ERROR, CONTROL_CASEFUL_LOCAL_PART, CONTROL_CASELOWER_LOCAL_PART,
- CONTROL_ENFORCE_SYNC, CONTROL_NO_ENFORCE_SYNC, CONTROL_FREEZE,
- CONTROL_QUEUE_ONLY, CONTROL_SUBMISSION, CONTROL_SUPPRESS_LOCAL_FIXUPS,
-#ifdef WITH_CONTENT_SCAN
+ #endif
+ CONTROL_ERROR,
+ CONTROL_CASEFUL_LOCAL_PART,
+ CONTROL_CASELOWER_LOCAL_PART,
+ CONTROL_ENFORCE_SYNC,
+ CONTROL_NO_ENFORCE_SYNC,
+ CONTROL_FREEZE,
+ CONTROL_QUEUE_ONLY,
+ CONTROL_SUBMISSION,
+ CONTROL_SUPPRESS_LOCAL_FIXUPS,
+ #ifdef WITH_CONTENT_SCAN
CONTROL_NO_MBOX_UNSPOOL,
-#endif
- CONTROL_FAKEDEFER, CONTROL_FAKEREJECT, CONTROL_NO_MULTILINE };
+ #endif
+ CONTROL_FAKEDEFER,
+ CONTROL_FAKEREJECT,
+ CONTROL_NO_MULTILINE
+};
/* ACL control names; keep in step with the table above! This list is used for
turning ids into names. The actual list of recognized names is in the variable
and should be tidied up. */
static uschar *controls[] = {
+ US"allow_auth_unadvertised",
#ifdef EXPERIMENTAL_BRIGHTMAIL
US"bmi_run",
#endif
#ifdef EXPERIMENTAL_DOMAINKEYS
US"dk_verify",
#endif
- US"error", US"caseful_local_part",
- US"caselower_local_part", US"enforce_sync", US"no_enforce_sync", US"freeze",
- US"queue_only", US"submission", US"suppress_local_fixups",
+ US"error",
+ US"caseful_local_part",
+ US"caselower_local_part",
+ US"enforce_sync",
+ US"no_enforce_sync",
+ US"freeze",
+ US"queue_only",
+ US"submission",
+ US"suppress_local_fixups",
#ifdef WITH_CONTENT_SCAN
US"no_mbox_unspool",
#endif
-
- US"no_multiline"};
+ US"no_multiline"
+};
/* Flags to indicate for which conditions /modifiers a string expansion is done
at the outer level. In the other cases, expansion already occurs in the
specify the negation of a small number of allowed times. */
static unsigned int control_forbids[] = {
-#ifdef EXPERIMENTAL_BRIGHTMAIL
+ (unsigned int)
+ ~((1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)), /* allow_auth_unadvertised */
+
+ #ifdef EXPERIMENTAL_BRIGHTMAIL
0, /* bmi_run */
-#endif
-#ifdef EXPERIMENTAL_DOMAINKEYS
+ #endif
+
+ #ifdef EXPERIMENTAL_DOMAINKEYS
(1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP), /* dk_verify */
-#endif
+ #endif
0, /* error */
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* suppress_local_fixups */
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_PREDATA)),
-#ifdef WITH_CONTENT_SCAN
+ #ifdef WITH_CONTENT_SCAN
(unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* no_mbox_unspool */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
(1<<ACL_WHERE_MIME)),
-#endif
+ #endif
(unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* fakedefer */
} control_def;
static control_def controls_list[] = {
+ { US"allow_auth_unadvertised", CONTROL_AUTH_UNADVERTISED, FALSE },
#ifdef EXPERIMENTAL_BRIGHTMAIL
- { US"bmi_run", CONTROL_BMI_RUN, FALSE },
+ { US"bmi_run", CONTROL_BMI_RUN, FALSE },
#endif
#ifdef EXPERIMENTAL_DOMAINKEYS
- { US"dk_verify", CONTROL_DK_VERIFY, FALSE },
-#endif
- { US"caseful_local_part", CONTROL_CASEFUL_LOCAL_PART, FALSE },
- { US"caselower_local_part", CONTROL_CASELOWER_LOCAL_PART, FALSE },
- { US"enforce_sync", CONTROL_ENFORCE_SYNC, FALSE },
- { US"freeze", CONTROL_FREEZE, FALSE },
- { US"no_enforce_sync", CONTROL_NO_ENFORCE_SYNC, FALSE },
- { US"no_multiline_responses", CONTROL_NO_MULTILINE, FALSE },
- { US"queue_only", CONTROL_QUEUE_ONLY, FALSE },
+ { US"dk_verify", CONTROL_DK_VERIFY, FALSE },
+#endif
+ { US"caseful_local_part", CONTROL_CASEFUL_LOCAL_PART, FALSE },
+ { US"caselower_local_part", CONTROL_CASELOWER_LOCAL_PART, FALSE },
+ { US"enforce_sync", CONTROL_ENFORCE_SYNC, FALSE },
+ { US"freeze", CONTROL_FREEZE, TRUE },
+ { US"no_enforce_sync", CONTROL_NO_ENFORCE_SYNC, FALSE },
+ { US"no_multiline_responses", CONTROL_NO_MULTILINE, FALSE },
+ { US"queue_only", CONTROL_QUEUE_ONLY, FALSE },
#ifdef WITH_CONTENT_SCAN
- { US"no_mbox_unspool", CONTROL_NO_MBOX_UNSPOOL, FALSE },
+ { US"no_mbox_unspool", CONTROL_NO_MBOX_UNSPOOL, FALSE },
#endif
- { US"fakedefer", CONTROL_FAKEDEFER, TRUE },
- { US"fakereject", CONTROL_FAKEREJECT, TRUE },
- { US"submission", CONTROL_SUBMISSION, TRUE },
- { US"suppress_local_fixups", CONTROL_SUPPRESS_LOCAL_FIXUPS, FALSE }
+ { US"fakedefer", CONTROL_FAKEDEFER, TRUE },
+ { US"fakereject", CONTROL_FAKEREJECT, TRUE },
+ { US"submission", CONTROL_SUBMISSION, TRUE },
+ { US"suppress_local_fixups", CONTROL_SUPPRESS_LOCAL_FIXUPS, FALSE }
};
/* Support data structures for Client SMTP Authorization. acl_verify_csa()
if (c == ACLC_SET)
{
- if (Ustrncmp(s, "acl_", 4) != 0 || (s[4] != 'c' && s[4] != 'm') ||
- !isdigit(s[5]) || (!isspace(s[6]) && s[6] != '='))
+ int offset, max, n;
+ uschar *endptr;
+
+ if (Ustrncmp(s, "acl_", 4) != 0) goto BAD_ACL_VAR;
+ if (s[4] == 'c')
+ {
+ offset = 0;
+ max = ACL_CVARS;
+ }
+ else if (s[4] == 'm')
{
- *error = string_sprintf("unrecognized name after \"set\" in ACL "
- "modifier \"set %s\"", s);
+ offset = ACL_CVARS;
+ max = ACL_MVARS;
+ }
+ else goto BAD_ACL_VAR;
+
+ n = Ustrtoul(s + 5, &endptr, 10);
+ if ((*endptr != 0 && *endptr != '=' && !isspace(*endptr)) || n >= max)
+ {
+ BAD_ACL_VAR:
+ *error = string_sprintf("syntax error or unrecognized name after "
+ "\"set\" in ACL modifier \"set %s\"", s);
return NULL;
}
- cond->u.varnumber = s[5] - '0';
- if (s[4] == 'm') cond->u.varnumber += ACL_C_MAX;
- s += 6;
+ cond->u.varnumber = n + offset;
+ s = endptr;
while (isspace(*s)) s++;
}
address literals, but it's probably the most friendly thing to do. This is an
extension to CSA, so we allow it to be turned off for proper conformance. */
-if (string_is_ip_address(domain, NULL))
+if (string_is_ip_address(domain, NULL) != 0)
{
if (!dns_csa_use_reverse) return CSA_UNKNOWN;
dns_build_reverse(domain, target);
if (cb->type == ACLC_SET)
{
int n = cb->u.varnumber;
- int t = (n < ACL_C_MAX)? 'c' : 'm';
- if (n >= ACL_C_MAX) n -= ACL_C_MAX;
+ int t = (n < ACL_CVARS)? 'c' : 'm';
+ if (n >= ACL_CVARS) n -= ACL_CVARS;
debug_printf("acl_%c%d ", t, n);
lhswidth += 7;
}
{
/* A nested ACL that returns "discard" makes sense only for an "accept" or
"discard" verb. */
-
+\
case ACLC_ACL:
rc = acl_check_internal(where, addr, arg, level+1, user_msgptr, log_msgptr);
if (rc == DISCARD && verb != ACL_ACCEPT && verb != ACL_DISCARD)
switch(control_type)
{
-#ifdef EXPERIMENTAL_BRIGHTMAIL
+ case CONTROL_AUTH_UNADVERTISED:
+ allow_auth_unadvertised = TRUE;
+ break;
+
+ #ifdef EXPERIMENTAL_BRIGHTMAIL
case CONTROL_BMI_RUN:
bmi_run = 1;
break;
-#endif
-#ifdef EXPERIMENTAL_DOMAINKEYS
+ #endif
+
+ #ifdef EXPERIMENTAL_DOMAINKEYS
case CONTROL_DK_VERIFY:
dk_do_verify = 1;
break;
-#endif
+ #endif
+
case CONTROL_ERROR:
return ERROR;
smtp_enforce_sync = FALSE;
break;
-#ifdef WITH_CONTENT_SCAN
+ #ifdef WITH_CONTENT_SCAN
case CONTROL_NO_MBOX_UNSPOOL:
no_mbox_unspool = TRUE;
break;
-#endif
+ #endif
case CONTROL_NO_MULTILINE:
no_multiline_responses = TRUE;
case CONTROL_FREEZE:
deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
+ freeze_tell = freeze_tell_config; /* Reset to configured value */
+ if (Ustrncmp(p, "/no_tell", 8) == 0)
+ {
+ p += 8;
+ freeze_tell = NULL;
+ }
+ if (*p != 0)
+ {
+ *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg);
+ return ERROR;
+ }
break;
case CONTROL_QUEUE_ONLY:
case ACLC_SET:
{
int old_pool = store_pool;
- if (cb->u.varnumber < ACL_C_MAX) store_pool = POOL_PERM;
+ if (cb->u.varnumber < ACL_CVARS) store_pool = POOL_PERM;
acl_var[cb->u.varnumber] = string_copy(arg);
store_pool = old_pool;
}
case ACL_WARN:
if (cond == OK)
acl_warn(where, *user_msgptr, *log_msgptr);
- else if (cond == DEFER)
+ else if (cond == DEFER && (log_extra_selector & LX_acl_warn_skipped) != 0)
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": ",