-/* $Cambridge: exim/src/src/acl.c,v 1.15 2005/01/12 14:23:28 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.26 2005/03/29 10:56:48 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
ACLC_DELAY,
#ifdef WITH_OLD_DEMIME
ACLC_DEMIME,
-#endif
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ ACLC_DK_DOMAIN_SOURCE,
+ ACLC_DK_POLICY,
+ ACLC_DK_SENDER_DOMAINS,
+ ACLC_DK_SENDER_LOCAL_PARTS,
+ ACLC_DK_SENDERS,
+ ACLC_DK_STATUS,
+#endif
ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS,
ACLC_HOSTS, ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE,
#ifdef WITH_CONTENT_SCAN
#endif
ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET,
#ifdef WITH_CONTENT_SCAN
- ACLC_SPAM,
+ ACLC_SPAM,
#endif
#ifdef EXPERIMENTAL_SPF
ACLC_SPF,
US"bmi_optin",
#endif
US"condition",
- US"control",
+ US"control",
#ifdef WITH_CONTENT_SCAN
US"decode",
#endif
US"delay",
#ifdef WITH_OLD_DEMIME
US"demime",
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ US"dk_domain_source",
+ US"dk_policy",
+ US"dk_sender_domains",
+ US"dk_sender_local_parts",
+ 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"spf",
#endif
US"verify" };
-
+
/* ACL control names */
static uschar *controls[] = { 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"no_multiline"};
+ US"queue_only", US"submission", 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
FALSE, /* authenticated */
#ifdef EXPERIMENTAL_BRIGHTMAIL
TRUE, /* bmi_optin */
-#endif
+#endif
TRUE, /* condition */
TRUE, /* control */
#ifdef WITH_CONTENT_SCAN
TRUE, /* delay */
#ifdef WITH_OLD_DEMIME
TRUE, /* demime */
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ TRUE, /* dk_domain_source */
+ TRUE, /* dk_policy */
+ TRUE, /* dk_sender_domains */
+ TRUE, /* dk_sender_local_parts */
+ TRUE, /* dk_senders */
+ TRUE, /* dk_status */
#endif
TRUE, /* dnslists */
FALSE, /* domains */
FALSE, /* authenticated */
#ifdef EXPERIMENTAL_BRIGHTMAIL
TRUE, /* bmi_optin */
-#endif
+#endif
FALSE, /* condition */
TRUE, /* control */
#ifdef WITH_CONTENT_SCAN
TRUE, /* delay */
#ifdef WITH_OLD_DEMIME
FALSE, /* demime */
+#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ FALSE, /* dk_domain_source */
+ FALSE, /* dk_policy */
+ FALSE, /* dk_sender_domains */
+ FALSE, /* dk_sender_local_parts */
+ FALSE, /* dk_senders */
+ FALSE, /* dk_status */
#endif
FALSE, /* dnslists */
FALSE, /* domains */
};
/* Bit map vector of which conditions are not allowed at certain times. For
-each condition, there's a bitmap of dis-allowed times. */
+each condition, 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 */
-
+
(1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)| /* authenticated */
(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)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
+ (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),
#endif
-
+
0, /* condition */
-
+
/* Certain types of control are always allowed, so we let it through
- always and check in the control processing itself */
-
+ always and check in the control processing itself. */
+
0, /* control */
-
+
#ifdef WITH_CONTENT_SCAN
- (1<<ACL_WHERE_AUTH)| /* decode */
- (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
- (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_RCPT),
+ (unsigned int)
+ ~(1<<ACL_WHERE_MIME), /* decode */
#endif
0, /* delay */
-
+
#ifdef WITH_OLD_DEMIME
- (1<<ACL_WHERE_AUTH)| /* demime */
- (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
- (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)), /* demime */
#endif
-
- (1<<ACL_WHERE_NOTSMTP), /* dnslists */
- (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)| /* domains */
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ (1<<ACL_WHERE_AUTH)| /* dk_domain_source */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
(1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
(1<<ACL_WHERE_VRFY),
- (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)| /* encrypted */
- (1<<ACL_WHERE_HELO),
-
- 0, /* endpass */
-
- (1<<ACL_WHERE_NOTSMTP), /* hosts */
-
- (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)| /* local_parts */
+ (1<<ACL_WHERE_AUTH)| /* dk_policy */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
(1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
(1<<ACL_WHERE_VRFY),
- 0, /* log_message */
-
- 0, /* logwrite */
-
-#ifdef WITH_CONTENT_SCAN
- (1<<ACL_WHERE_AUTH)| /* malware */
+ (1<<ACL_WHERE_AUTH)| /* dk_sender_domains */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
(1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
(1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
-#endif
-
- 0, /* message */
+ (1<<ACL_WHERE_VRFY),
-#ifdef WITH_CONTENT_SCAN
- (1<<ACL_WHERE_AUTH)| /* mime_regex */
+ (1<<ACL_WHERE_AUTH)| /* dk_sender_local_parts */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
(1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_RCPT),
-#endif
+ (1<<ACL_WHERE_VRFY),
- (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)| /* recipients */
+ (1<<ACL_WHERE_AUTH)| /* dk_senders */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
+ (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
(1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
(1<<ACL_WHERE_VRFY),
-#ifdef WITH_CONTENT_SCAN
- (1<<ACL_WHERE_AUTH)| /* regex */
+ (1<<ACL_WHERE_AUTH)| /* dk_status */
(1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
(1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
(1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
(1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
(1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
+ (1<<ACL_WHERE_VRFY),
+#endif
+
+ (1<<ACL_WHERE_NOTSMTP), /* dnslists */
+
+ (unsigned int)
+ ~(1<<ACL_WHERE_RCPT), /* domains */
+
+ (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)| /* encrypted */
+ (1<<ACL_WHERE_HELO),
+
+ 0, /* endpass */
+
+ (1<<ACL_WHERE_NOTSMTP), /* hosts */
+
+ (unsigned int)
+ ~(1<<ACL_WHERE_RCPT), /* local_parts */
+
+ 0, /* log_message */
+
+ 0, /* logwrite */
+
+#ifdef WITH_CONTENT_SCAN
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)), /* malware */
+#endif
+
+ 0, /* message */
+
+#ifdef WITH_CONTENT_SCAN
+ (unsigned int)
+ ~(1<<ACL_WHERE_MIME), /* mime_regex */
+#endif
+
+ (unsigned int)
+ ~(1<<ACL_WHERE_RCPT), /* recipients */
+
+#ifdef WITH_CONTENT_SCAN
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)| /* regex */
+ (1<<ACL_WHERE_MIME)),
#endif
(1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)| /* sender_domains */
0, /* set */
#ifdef WITH_CONTENT_SCAN
- (1<<ACL_WHERE_AUTH)| /* spam */
- (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
- (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
- (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
- (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
- (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
- (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
+ (unsigned int)
+ ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)), /* spam */
#endif
#ifdef EXPERIMENTAL_SPF
/* Return values from decode_control() */
-enum {
+enum {
#ifdef EXPERIMENTAL_BRIGHTMAIL
CONTROL_BMI_RUN,
-#endif
+#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,
#ifdef WITH_CONTENT_SCAN
- CONTROL_NO_MBOX_UNSPOOL,
+ CONTROL_NO_MBOX_UNSPOOL,
#endif
CONTROL_FAKEREJECT, CONTROL_NO_MULTILINE };
#ifdef EXPERIMENTAL_BRIGHTMAIL
0, /* bmi_run */
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP), /* dk_verify */
+#endif
0, /* error */
-
- (unsigned int)
+
+ (unsigned int)
~(1<<ACL_WHERE_RCPT), /* caseful_local_part */
-
- (unsigned int)
+
+ (unsigned int)
~(1<<ACL_WHERE_RCPT), /* caselower_local_part */
-
+
(1<<ACL_WHERE_NOTSMTP), /* enforce_sync */
-
+
(1<<ACL_WHERE_NOTSMTP), /* no_enforce_sync */
-
- (unsigned int)
+
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* freeze */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
- (1<<ACL_WHERE_NOTSMTP)),
-
- (unsigned int)
+ (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_MIME)),
+
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* queue_only */
(1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
- (1<<ACL_WHERE_NOTSMTP)),
-
- (unsigned int)
+ (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_MIME)),
+
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* submission */
- (1<<ACL_WHERE_PREDATA)),
+ (1<<ACL_WHERE_PREDATA)),
#ifdef WITH_CONTENT_SCAN
- (unsigned int)
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* no_mbox_unspool */
- (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)),
+ (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
+ (1<<ACL_WHERE_MIME)),
#endif
- (unsigned int)
+ (unsigned int)
~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)| /* fakereject */
- (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)),
+ (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
+ (1<<ACL_WHERE_MIME)),
(1<<ACL_WHERE_NOTSMTP) /* no_multiline */
};
static control_def controls_list[] = {
#ifdef EXPERIMENTAL_BRIGHTMAIL
{ 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},
{
newtype = htype_add_rfc;
p += 14;
- }
+ }
else if (strncmpic(p, US":at_start:", 10) == 0)
{
newtype = htype_add_top;
uschar *verify_sender_address = NULL;
uschar *pm_mailfrom = NULL;
uschar *se_mailfrom = NULL;
+
+/* Some of the verify items have slash-separated options; some do not. Diagnose
+an error if options are given for items that don't expect them. This code has
+now got very message. Refactoring to use a table would be a good idea one day.
+*/
+
+uschar *slash = Ustrchr(arg, '/');
uschar *list = arg;
uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size);
if (strcmpic(ss, US"reverse_host_lookup") == 0)
{
+ if (slash != NULL) goto NO_OPTIONS;
if (sender_host_address == NULL) return OK;
return acl_verify_reverse(user_msgptr, log_msgptr);
}
if (strcmpic(ss, US"certificate") == 0)
{
+ if (slash != NULL) goto NO_OPTIONS;
if (tls_certificate_verified) return OK;
*user_msgptr = US"no verified certificate";
return FAIL;
/* We can test the result of optional HELO verification */
-if (strcmpic(ss, US"helo") == 0) return helo_verified? OK : FAIL;
+if (strcmpic(ss, US"helo") == 0)
+ {
+ if (slash != NULL) goto NO_OPTIONS;
+ return helo_verified? OK : FAIL;
+ }
-/* Handle header verification options - permitted only after DATA or a non-SMTP
-message. */
+/* Check that all relevant header lines have the correct syntax. If there is
+a syntax error, we return details of the error to the sender if configured to
+send out full details. (But a "message" setting on the ACL can override, as
+always). */
-if (strncmpic(ss, US"header_", 7) == 0)
+if (strcmpic(ss, US"header_syntax") == 0)
{
+ if (slash != NULL) goto NO_OPTIONS;
if (where != ACL_WHERE_DATA && where != ACL_WHERE_NOTSMTP)
{
*log_msgptr = string_sprintf("cannot check header contents in ACL for %s "
"(only possible in ACL for DATA)", acl_wherenames[where]);
return ERROR;
}
+ rc = verify_check_headers(log_msgptr);
+ if (rc != OK && smtp_return_error_details && *log_msgptr != NULL)
+ *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
+ return rc;
+ }
- /* Check that all relevant header lines have the correct syntax. If there is
- a syntax error, we return details of the error to the sender if configured to
- send out full details. (But a "message" setting on the ACL can override, as
- always). */
-
- if (strcmpic(ss+7, US"syntax") == 0)
- {
- int rc = verify_check_headers(log_msgptr);
- if (rc != OK && smtp_return_error_details && *log_msgptr != NULL)
- *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
- return rc;
- }
- /* Check that there is at least one verifiable sender address in the relevant
- header lines. This can be followed by callout and defer options, just like
- sender and recipient. */
+/* The remaining verification tests check recipient and sender addresses,
+either from the envelope or from the header. There are a number of
+slash-separated options that are common to all of them. */
- else if (strcmpic(ss+7, US"sender") == 0) verify_header_sender = TRUE;
- /* Unknown verify argument starting with "header_" */
+/* Check that there is at least one verifiable sender address in the relevant
+header lines. This can be followed by callout and defer options, just like
+sender and recipient. */
- else goto BAD_VERIFY;
+if (strcmpic(ss, US"header_sender") == 0)
+ {
+ if (where != ACL_WHERE_DATA && where != ACL_WHERE_NOTSMTP)
+ {
+ *log_msgptr = string_sprintf("cannot check header contents in ACL for %s "
+ "(only possible in ACL for DATA)", acl_wherenames[where]);
+ return ERROR;
+ }
+ verify_header_sender = TRUE;
}
/* Otherwise, first item in verify argument must be "sender" or "recipient".
}
}
-/* Remaining items are optional */
+/* Remaining items are optional; they apply to sender and recipient
+verification, including "header sender" verification. */
while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))
!= NULL)
uschar *opt;
uschar buffer[256];
while (isspace(*ss)) ss++;
-
- /* This callout option handling code has become a mess as new options
- have been added in an ad hoc manner. It should be tidied up into some
+
+ /* This callout option handling code has become a mess as new options
+ have been added in an ad hoc manner. It should be tidied up into some
kind of table-driven thing. */
-
+
while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer)))
!= NULL)
{
if (verify_header_sender)
{
+ int verrno;
rc = verify_check_header_address(user_msgptr, log_msgptr, callout,
- callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options);
- if (smtp_return_error_details)
+ callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options,
+ &verrno);
+ if (rc != OK)
{
- if (*user_msgptr == NULL && *log_msgptr != NULL)
- *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
- if (rc == DEFER) acl_temp_details = TRUE;
+ *basic_errno = verrno;
+ if (smtp_return_error_details)
+ {
+ if (*user_msgptr == NULL && *log_msgptr != NULL)
+ *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
+ if (rc == DEFER) acl_temp_details = TRUE;
+ }
}
}
{
BOOL routed = TRUE;
uschar *save_address_data = deliver_address_data;
-
+
sender_vaddr = deliver_make_addr(verify_sender_address, TRUE);
if (no_details) setflag(sender_vaddr, af_sverify_told);
if (verify_sender_address[0] != 0)
sender_vaddr->special_action = rc;
sender_vaddr->next = sender_verified_list;
sender_verified_list = sender_vaddr;
-
- /* Restore the recipient address data, which might have been clobbered by
+
+ /* Restore the recipient address data, which might have been clobbered by
the sender verification. */
-
+
deliver_address_data = save_address_data;
}
-
+
/* Put the sender address_data value into $sender_address_data */
- sender_address_data = sender_vaddr->p.address_data;
+ sender_address_data = sender_vaddr->p.address_data;
}
/* A recipient address just gets a straightforward verify; again we must handle
rc = verify_address(&addr2, NULL, verify_options|vopt_is_recipient, callout,
callout_overall, callout_connect, se_mailfrom, pm_mailfrom, NULL);
HDEBUG(D_acl) debug_printf("----------- end verify ------------\n");
+
*log_msgptr = addr2.message;
- *user_msgptr = addr2.user_message;
+ *user_msgptr = (addr2.user_message != NULL)?
+ addr2.user_message : addr2.message;
*basic_errno = addr2.basic_errno;
/* Make $address_data visible */
BAD_VERIFY:
*log_msgptr = string_sprintf("expected \"sender[=address]\", \"recipient\", "
- "\"header_syntax\" or \"header_sender\" at start of ACL condition "
+ "\"helo\", \"header_syntax\", \"header_sender\" or "
+ "\"reverse_host_lookup\" at start of ACL condition "
"\"verify %s\"", arg);
return ERROR;
+
+/* Options supplied when not allowed come here */
+
+NO_OPTIONS:
+*log_msgptr = string_sprintf("unexpected '/' found in \"%s\" "
+ "(this verify item has no options)", arg);
+return ERROR;
}
for (; cb != NULL; cb = cb->next)
{
uschar *arg;
- int control_type;
+ int control_type;
/* The message and log_message items set up messages to be used in
case of rejection. They are expanded later. */
*log_msgptr = string_sprintf("cannot use \"control=%s\" in %s ACL",
controls[control_type], acl_wherenames[where]);
return ERROR;
- }
+ }
switch(control_type)
{
bmi_run = 1;
break;
#endif
-
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ case CONTROL_DK_VERIFY:
+ dk_do_verify = 1;
+ break;
+#endif
case CONTROL_ERROR:
return ERROR;
case CONTROL_FAKEREJECT:
fake_reject = TRUE;
if (*p == '/')
- {
+ {
uschar *pp = p + 1;
- while (*pp != 0) pp++;
+ while (*pp != 0) pp++;
fake_reject_text = expand_string(string_copyn(p+1, pp-p));
p = pp;
}
else
{
/* Explicitly reset to default string */
- fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legit message, it may still be delivered to the target recipient(s).";
+ fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legitimate message, it may still be delivered to the target recipient(s).";
}
break;
case CONTROL_SUBMISSION:
submission_mode = TRUE;
while (*p == '/')
- {
+ {
if (Ustrncmp(p, "/sender_retain", 14) == 0)
{
p += 14;
active_local_sender_retain = TRUE;
- active_local_from_check = FALSE;
- }
+ active_local_from_check = FALSE;
+ }
else if (Ustrncmp(p, "/domain=", 8) == 0)
{
uschar *pp = p + 8;
- while (*pp != 0 && *pp != '/') pp++;
+ while (*pp != 0 && *pp != '/') pp++;
submission_domain = string_copyn(p+8, pp-p);
- p = pp;
+ p = pp;
}
- else break;
- }
+ else break;
+ }
if (*p != 0)
{
*log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg);
HDEBUG(D_acl)
debug_printf("delay skipped in -bh checking mode\n");
}
- else
+ else
{
while (delay > 0) delay = sleep(delay);
- }
+ }
}
}
break;
break;
#endif
+#ifdef EXPERIMENTAL_DOMAINKEYS
+ case ACLC_DK_DOMAIN_SOURCE:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ /* check header source of domain against given string */
+ switch (dk_verify_block->address_source) {
+ case DK_EXIM_ADDRESS_FROM_FROM:
+ rc = match_isinlist(US"from", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_ADDRESS_FROM_SENDER:
+ rc = match_isinlist(US"sender", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_ADDRESS_NONE:
+ rc = match_isinlist(US"none", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ }
+ break;
+ case ACLC_DK_POLICY:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ /* check policy against given string, default FAIL */
+ rc = FAIL;
+ if (dk_verify_block->signsall)
+ rc = match_isinlist(US"signsall", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ if (dk_verify_block->testing)
+ rc = match_isinlist(US"testing", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case ACLC_DK_SENDER_DOMAINS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->domain != NULL)
+ rc = match_isinlist(dk_verify_block->domain, &arg, 0, &domainlist_anchor,
+ NULL, MCL_DOMAIN, TRUE, NULL);
+ else rc = FAIL;
+ break;
+ case ACLC_DK_SENDER_LOCAL_PARTS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->local_part != NULL)
+ rc = match_isinlist(dk_verify_block->local_part, &arg, 0, &localpartlist_anchor,
+ NULL, MCL_LOCALPART, TRUE, NULL);
+ else rc = FAIL;
+ break;
+ case ACLC_DK_SENDERS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->address != NULL)
+ rc = match_address_list(dk_verify_block->address, TRUE, TRUE, &arg, NULL, -1, 0, NULL);
+ else rc = FAIL;
+ break;
+ case ACLC_DK_STATUS:
+ if (dk_verify_block == NULL) { rc = FAIL; break; };
+ if (dk_verify_block->result > 0) {
+ switch(dk_verify_block->result) {
+ case DK_EXIM_RESULT_BAD_FORMAT:
+ rc = match_isinlist(US"bad format", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_NO_KEY:
+ rc = match_isinlist(US"no key", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_NO_SIGNATURE:
+ rc = match_isinlist(US"no signature", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_REVOKED:
+ rc = match_isinlist(US"revoked", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_NON_PARTICIPANT:
+ rc = match_isinlist(US"non-participant", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_GOOD:
+ rc = match_isinlist(US"good", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ case DK_EXIM_RESULT_BAD:
+ rc = match_isinlist(US"bad", &arg, 0, NULL,
+ NULL, MCL_STRING, TRUE, NULL);
+ break;
+ }
+ }
+ break;
+#endif
+
case ACLC_DNSLISTS:
rc = verify_check_dnsbl(&arg);
break;
log_write(0, logbits, "%s", string_printing(s));
}
break;
-
+
#ifdef WITH_CONTENT_SCAN
case ACLC_MALWARE:
{