X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Facl.c;h=8fb6a7eeff62143a8885d7e038728c02ed839957;hb=bf759a8bd76d74e3be65879d6d0a871a0aad96c1;hp=92ebc18ec7d3e785d0339b9f975e65a63eb64d37;hpb=4deaf07d6cdd04468e4bc383945b9e19d7d55aa3;p=exim.git diff --git a/src/src/acl.c b/src/src/acl.c index 92ebc18ec..8fb6a7eef 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.5 2004/11/04 12:19:48 ph10 Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.25 2005/03/15 15:36:41 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2005 */ /* See the file NOTICE for conditions of use and distribution. */ /* Code for handling Access Control Lists (ACLs) */ @@ -34,26 +34,100 @@ static int msgcond[] = { FAIL, OK, OK, FAIL, OK, FAIL, OK }; /* ACL condition and modifier codes - keep in step with the table that follows. */ -enum { ACLC_ACL, ACLC_AUTHENTICATED, ACLC_CONDITION, ACLC_CONTROL, ACLC_DELAY, - ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS, ACLC_HOSTS, - ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE, ACLC_MESSAGE, - ACLC_RECIPIENTS, ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET, ACLC_VERIFY }; +enum { ACLC_ACL, ACLC_AUTHENTICATED, +#ifdef EXPERIMENTAL_BRIGHTMAIL + ACLC_BMI_OPTIN, +#endif +ACLC_CONDITION, ACLC_CONTROL, +#ifdef WITH_CONTENT_SCAN + ACLC_DECODE, +#endif + ACLC_DELAY, +#ifdef WITH_OLD_DEMIME + ACLC_DEMIME, +#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 + ACLC_MALWARE, +#endif + ACLC_MESSAGE, +#ifdef WITH_CONTENT_SCAN + ACLC_MIME_REGEX, +#endif + ACLC_RECIPIENTS, +#ifdef WITH_CONTENT_SCAN + ACLC_REGEX, +#endif + ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET, +#ifdef WITH_CONTENT_SCAN + ACLC_SPAM, +#endif +#ifdef EXPERIMENTAL_SPF + ACLC_SPF, +#endif + 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. */ -static uschar *conditions[] = { US"acl", US"authenticated", US"condition", - US"control", US"delay", US"dnslists", US"domains", US"encrypted", +static uschar *conditions[] = { US"acl", US"authenticated", +#ifdef EXPERIMENTAL_BRIGHTMAIL + US"bmi_optin", +#endif + US"condition", + 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"message", US"recipients", US"sender_domains", US"senders", US"set", +#ifdef WITH_CONTENT_SCAN + US"malware", +#endif + US"message", +#ifdef WITH_CONTENT_SCAN + US"mime_regex", +#endif + US"recipients", +#ifdef WITH_CONTENT_SCAN + US"regex", +#endif + US"sender_domains", US"senders", US"set", +#ifdef WITH_CONTENT_SCAN + US"spam", +#endif +#ifdef EXPERIMENTAL_SPF + 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 @@ -62,9 +136,26 @@ checking functions. */ static uschar cond_expand_at_top[] = { TRUE, /* acl */ FALSE, /* authenticated */ +#ifdef EXPERIMENTAL_BRIGHTMAIL + TRUE, /* bmi_optin */ +#endif TRUE, /* condition */ TRUE, /* control */ +#ifdef WITH_CONTENT_SCAN + TRUE, /* decode */ +#endif 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, /* encrypted */ @@ -73,11 +164,26 @@ static uschar cond_expand_at_top[] = { FALSE, /* local_parts */ TRUE, /* log_message */ TRUE, /* logwrite */ +#ifdef WITH_CONTENT_SCAN + TRUE, /* malware */ +#endif TRUE, /* message */ +#ifdef WITH_CONTENT_SCAN + TRUE, /* mime_regex */ +#endif FALSE, /* recipients */ +#ifdef WITH_CONTENT_SCAN + TRUE, /* regex */ +#endif FALSE, /* sender_domains */ FALSE, /* senders */ TRUE, /* set */ +#ifdef WITH_CONTENT_SCAN + TRUE, /* spam */ +#endif +#ifdef EXPERIMENTAL_SPF + TRUE, /* spf */ +#endif TRUE /* verify */ }; @@ -86,9 +192,26 @@ static uschar cond_expand_at_top[] = { static uschar cond_modifiers[] = { FALSE, /* acl */ FALSE, /* authenticated */ +#ifdef EXPERIMENTAL_BRIGHTMAIL + TRUE, /* bmi_optin */ +#endif FALSE, /* condition */ TRUE, /* control */ +#ifdef WITH_CONTENT_SCAN + FALSE, /* decode */ +#endif 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 */ FALSE, /* encrypted */ @@ -96,12 +219,27 @@ static uschar cond_modifiers[] = { FALSE, /* hosts */ FALSE, /* local_parts */ TRUE, /* log_message */ - TRUE, /* log_write */ + TRUE, /* logwrite */ +#ifdef WITH_CONTENT_SCAN + FALSE, /* malware */ +#endif TRUE, /* message */ +#ifdef WITH_CONTENT_SCAN + FALSE, /* mime_regex */ +#endif FALSE, /* recipients */ +#ifdef WITH_CONTENT_SCAN + FALSE, /* regex */ +#endif FALSE, /* sender_domains */ FALSE, /* senders */ TRUE, /* set */ +#ifdef WITH_CONTENT_SCAN + FALSE, /* spam */ +#endif +#ifdef EXPERIMENTAL_SPF + FALSE, /* spf */ +#endif FALSE /* verify */ }; @@ -110,15 +248,99 @@ each condition, there's a bitmap of dis-allowed times. */ static unsigned int cond_forbids[] = { 0, /* acl */ + (1< 0) newtype = htype_add_rec; p += 16; } + else if (strncmpic(p, US":at_start_rfc:", 14) == 0) + { + newtype = htype_add_rfc; + p += 14; + } else if (strncmpic(p, US":at_start:", 10) == 0) { newtype = htype_add_top; @@ -700,6 +1028,13 @@ address_item *sender_vaddr = NULL; 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); @@ -709,6 +1044,7 @@ if (ss == NULL) goto BAD_VERIFY; 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); } @@ -719,6 +1055,7 @@ mandatory verification, the connection doesn't last this long.) */ 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; @@ -726,42 +1063,51 @@ if (strcmpic(ss, US"certificate") == 0) /* 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; - } +/* 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. */ - /* 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 if (strcmpic(ss+7, US"sender") == 0) verify_header_sender = TRUE; +/* 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. */ - /* Unknown verify argument starting with "header_" */ - - 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". @@ -799,7 +1145,8 @@ else } } -/* 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) @@ -836,11 +1183,11 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) 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) { @@ -972,13 +1319,19 @@ message if giving out verification details. */ 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; + } } } @@ -1038,7 +1391,7 @@ else if (verify_sender_address != NULL) { 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) @@ -1084,16 +1437,16 @@ else if (verify_sender_address != NULL) 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 @@ -1110,8 +1463,10 @@ else 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 */ @@ -1165,9 +1520,17 @@ return rc; 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; } @@ -1253,11 +1616,14 @@ uschar *user_message = NULL; uschar *log_message = NULL; uschar *p; int rc = OK; +#ifdef WITH_CONTENT_SCAN +int sep = '/'; +#endif 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. */ @@ -1360,6 +1726,17 @@ for (; cb != NULL; cb = cb->next) TRUE, NULL); break; +#ifdef EXPERIMENTAL_BRIGHTMAIL + case ACLC_BMI_OPTIN: + { + int old_pool = store_pool; + store_pool = POOL_PERM; + bmi_current_optin = string_copy(arg); + store_pool = old_pool; + } + break; +#endif + case ACLC_CONDITION: if (Ustrspn(arg, "0123456789") == Ustrlen(arg)) /* Digits, or empty */ rc = (Uatoi(arg) == 0)? FAIL : OK; @@ -1375,17 +1752,27 @@ for (; cb != NULL; cb = cb->next) case ACLC_CONTROL: control_type = decode_control(arg, &p, where, log_msgptr); - /* Check this control makes sense at this time */ + /* Check if this control makes sense at this time */ if ((control_forbids[control_type] & (1 << where)) != 0) { *log_msgptr = string_sprintf("cannot use \"control=%s\" in %s ACL", controls[control_type], acl_wherenames[where]); return ERROR; - } + } switch(control_type) { +#ifdef EXPERIMENTAL_BRIGHTMAIL + case CONTROL_BMI_RUN: + bmi_run = 1; + break; +#endif +#ifdef EXPERIMENTAL_DOMAINKEYS + case CONTROL_DK_VERIFY: + dk_do_verify = 1; + break; +#endif case CONTROL_ERROR: return ERROR; @@ -1405,10 +1792,32 @@ for (; cb != NULL; cb = cb->next) smtp_enforce_sync = FALSE; break; +#ifdef WITH_CONTENT_SCAN + case CONTROL_NO_MBOX_UNSPOOL: + no_mbox_unspool = TRUE; + break; +#endif + case CONTROL_NO_MULTILINE: no_multiline_responses = TRUE; break; + case CONTROL_FAKEREJECT: + fake_reject = TRUE; + if (*p == '/') + { + uschar *pp = p + 1; + 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 legitimate message, it may still be delivered to the target recipient(s)."; + } + break; + case CONTROL_FREEZE: deliver_freeze = TRUE; deliver_frozen_at = time(NULL); @@ -1421,22 +1830,22 @@ for (; cb != NULL; cb = cb->next) 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); @@ -1446,6 +1855,12 @@ for (; cb != NULL; cb = cb->next) } break; +#ifdef WITH_CONTENT_SCAN + case ACLC_DECODE: + rc = mime_decode(&arg); + break; +#endif + case ACLC_DELAY: { int delay = readconf_readtime(arg, 0, FALSE); @@ -1464,11 +1879,107 @@ for (; cb != NULL; cb = cb->next) HDEBUG(D_acl) debug_printf("delay skipped in -bh checking mode\n"); } - else sleep(delay); + else + { + while (delay > 0) delay = sleep(delay); + } } } break; +#ifdef WITH_OLD_DEMIME + case ACLC_DEMIME: + rc = demime(&arg); + 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; @@ -1549,11 +2060,41 @@ for (; cb != NULL; cb = cb->next) } break; +#ifdef WITH_CONTENT_SCAN + case ACLC_MALWARE: + { + /* Seperate 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); + /* Modify return code based upon the existance of options. */ + while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size)) + != NULL) { + if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER) + { + /* FAIL so that the message is passed to the next ACL */ + rc = FAIL; + } + } + } + break; + + case ACLC_MIME_REGEX: + rc = mime_regex(&arg); + break; +#endif + case ACLC_RECIPIENTS: rc = match_address_list(addr->address, TRUE, TRUE, &arg, NULL, -1, 0, &recipient_data); break; +#ifdef WITH_CONTENT_SCAN + case ACLC_REGEX: + rc = regex(&arg); + break; +#endif + case ACLC_SENDER_DOMAINS: { uschar *sdomain; @@ -1580,6 +2121,32 @@ for (; cb != NULL; cb = cb->next) } break; +#ifdef WITH_CONTENT_SCAN + case ACLC_SPAM: + { + /* Seperate the regular expression and any optional parameters. */ + uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size); + /* Run the spam backend. */ + rc = spam(&ss); + /* Modify return code based upon the existance of options. */ + while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size)) + != NULL) { + if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER) + { + /* FAIL so that the message is passed to the next ACL */ + rc = FAIL; + } + } + } + break; +#endif + +#ifdef EXPERIMENTAL_SPF + case ACLC_SPF: + rc = spf_process(&arg, sender_address); + break; +#endif + /* If the verb is WARN, discard any user message from verification, because such messages are SMTP responses, not header additions. The latter come only from explicit "message" modifiers. */