X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/5a66c31b0ec1f4128df4398e18dfe497c2a34de7..93a6fce2ebf117f490d7ee11f066f75280d32386:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index 9d0842c1d..69db5cda7 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -397,7 +397,7 @@ static unsigned int cond_forbids[] = { (unsigned int) ~((1<text, s, hlen) == 0) break; + if (Ustrncmp((*hptr)->text, hdr, hlen) == 0) break; hptr = &((*hptr)->next); } @@ -1130,7 +1140,7 @@ for (p = q = hstring; *p != 0; ) if (*hptr == NULL) { header_line *h = store_get(sizeof(header_line)); - h->text = s; + h->text = hdr; h->next = NULL; h->type = newtype; h->slen = hlen; @@ -1197,15 +1207,12 @@ Returns: nothing */ static void -setup_remove_header(uschar *hnames) +setup_remove_header(const uschar *hnames) { if (*hnames != 0) - { - if (acl_removed_headers == NULL) - acl_removed_headers = hnames; - else - acl_removed_headers = string_sprintf("%s : %s", acl_removed_headers, hnames); - } + acl_removed_headers = acl_removed_headers + ? string_sprintf("%s : %s", acl_removed_headers, hnames) + : string_copy(hnames); } @@ -1444,10 +1451,11 @@ Returns: CSA_UNKNOWN no valid CSA record found */ static int -acl_verify_csa(uschar *domain) +acl_verify_csa(const uschar *domain) { tree_node *t; -uschar *found, *p; +const uschar *found; +uschar *p; int priority, weight, port; dns_answer dnsa; dns_scan dnss; @@ -1470,7 +1478,7 @@ containing a keyword and a colon before the actual IP address. */ if (domain[0] == '[') { - uschar *start = Ustrchr(domain, ':'); + const uschar *start = Ustrchr(domain, ':'); if (start == NULL) start = domain; domain = string_copyn(start + 1, Ustrlen(start) - 2); } @@ -1550,7 +1558,7 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); assertion: legitimate SMTP clients are all explicitly authorized with CSA SRV records of their own. */ - if (found != domain) + if (Ustrcmp(found, domain) != 0) { if (port & 1) return t->data.val = CSA_FAIL_EXPLICIT; @@ -1614,6 +1622,7 @@ else DNS_LOOKUP_AGAIN: #endif +lookup_dnssec_authenticated = NULL; switch (dns_lookup(&dnsa, target, type, NULL)) { /* If something bad happened (most commonly DNS_AGAIN), defer. */ @@ -1661,7 +1670,7 @@ typedef struct { unsigned alt_opt_sep; /* >0 Non-/ option separator (custom parser) */ } verify_type_t; static verify_type_t verify_type_list[] = { - { US"reverse_host_lookup", VERIFY_REV_HOST_LKUP, ~0, TRUE, 0 }, + { US"reverse_host_lookup", VERIFY_REV_HOST_LKUP, ~0, FALSE, 0 }, { US"certificate", VERIFY_CERT, ~0, TRUE, 0 }, { US"helo", VERIFY_HELO, ~0, TRUE, 0 }, { US"csa", VERIFY_CSA, ~0, FALSE, 0 }, @@ -1725,7 +1734,7 @@ Returns: OK verification condition succeeded */ static int -acl_verify(int where, address_item *addr, uschar *arg, +acl_verify(int where, address_item *addr, const uschar *arg, uschar **user_msgptr, uschar **log_msgptr, int *basic_errno) { int sep = '/'; @@ -1749,7 +1758,7 @@ an error if options are given for items that don't expect them. */ uschar *slash = Ustrchr(arg, '/'); -uschar *list = arg; +const uschar *list = arg; uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size); verify_type_t * vp; @@ -1782,7 +1791,11 @@ switch(vp->value) { case VERIFY_REV_HOST_LKUP: if (sender_host_address == NULL) return OK; - return acl_verify_reverse(user_msgptr, log_msgptr); + if ((rc = acl_verify_reverse(user_msgptr, log_msgptr)) == DEFER) + while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))) + if (strcmpic(ss, US"defer_ok") == 0) + return OK; + return rc; case VERIFY_CERT: /* TLS certificate verification is done at STARTTLS time; here we just @@ -1910,12 +1923,13 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) while (isspace(*ss)) ss++; if (*ss++ == '=') { + const uschar * sublist = ss; int optsep = ','; uschar *opt; uschar buffer[256]; - while (isspace(*ss)) ss++; + while (isspace(*sublist)) sublist++; - while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer))) + while ((opt = string_nextinlist(&sublist, &optsep, buffer, sizeof(buffer))) != NULL) { callout_opt_t * op; @@ -2238,7 +2252,7 @@ Returns: CONTROL_xxx value */ static int -decode_control(uschar *arg, uschar **pptr, int where, uschar **log_msgptr) +decode_control(const uschar *arg, const uschar **pptr, int where, uschar **log_msgptr) { int len; control_def *d; @@ -2323,7 +2337,7 @@ Returns: OK - Sender's rate is above limit */ static int -acl_ratelimit(uschar *arg, int where, uschar **log_msgptr) +acl_ratelimit(const uschar *arg, int where, uschar **log_msgptr) { double limit, period, count; uschar *ss; @@ -2351,7 +2365,10 @@ rate measurement as opposed to rate limiting. */ sender_rate_limit = string_nextinlist(&arg, &sep, NULL, 0); if (sender_rate_limit == NULL) + { limit = -1.0; + ss = NULL; /* compiler quietening */ + } else { limit = Ustrtod(sender_rate_limit, &ss); @@ -2849,7 +2866,7 @@ Returns: OK - Completed. */ static int -acl_udpsend(uschar *arg, uschar **log_msgptr) +acl_udpsend(const uschar *arg, uschar **log_msgptr) { int sep = 0; uschar *hostname; @@ -2975,15 +2992,14 @@ uschar *user_message = NULL; uschar *log_message = NULL; uschar *debug_tag = NULL; uschar *debug_opts = NULL; -uschar *p = NULL; int rc = OK; #ifdef WITH_CONTENT_SCAN -int sep = '/'; +int sep = -'/'; #endif for (; cb != NULL; cb = cb->next) { - uschar *arg; + const uschar *arg; int control_type; /* The message and log_message items set up messages to be used in @@ -2991,12 +3007,14 @@ for (; cb != NULL; cb = cb->next) if (cb->type == ACLC_MESSAGE) { + HDEBUG(D_acl) debug_printf(" message: %s\n", cb->arg); user_message = cb->arg; continue; } if (cb->type == ACLC_LOG_MESSAGE) { + HDEBUG(D_acl) debug_printf("l_message: %s\n", cb->arg); log_message = cb->arg; continue; } @@ -3120,255 +3138,272 @@ for (; cb != NULL; cb = cb->next) break; case ACLC_CONTROL: - control_type = decode_control(arg, &p, where, log_msgptr); - - /* 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) { - case CONTROL_AUTH_UNADVERTISED: - allow_auth_unadvertised = TRUE; - break; - - #ifdef EXPERIMENTAL_BRIGHTMAIL - case CONTROL_BMI_RUN: - bmi_run = 1; - break; - #endif - - #ifndef DISABLE_DKIM - case CONTROL_DKIM_VERIFY: - dkim_disable_verify = TRUE; - #ifdef EXPERIMENTAL_DMARC - /* Since DKIM was blocked, skip DMARC too */ - dmarc_disable_verify = TRUE; - dmarc_enable_forensic = FALSE; - #endif - break; - #endif - - #ifdef EXPERIMENTAL_DMARC - case CONTROL_DMARC_VERIFY: - dmarc_disable_verify = TRUE; - break; - - case CONTROL_DMARC_FORENSIC: - dmarc_enable_forensic = TRUE; - break; - #endif - - case CONTROL_DSCP: - if (*p == '/') - { - int fd, af, level, optname, value; - /* If we are acting on stdin, the setsockopt may fail if stdin is not - a socket; we can accept that, we'll just debug-log failures anyway. */ - fd = fileno(smtp_in); - af = ip_get_address_family(fd); - if (af < 0) - { - HDEBUG(D_acl) - debug_printf("smtp input is probably not a socket [%s], not setting DSCP\n", - strerror(errno)); - break; - } - if (dscp_lookup(p+1, af, &level, &optname, &value)) - { - if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0) - { - HDEBUG(D_acl) debug_printf("failed to set input DSCP[%s]: %s\n", - p+1, strerror(errno)); - } - else - { - HDEBUG(D_acl) debug_printf("set input DSCP to \"%s\"\n", p+1); - } - } - else - { - *log_msgptr = string_sprintf("unrecognised DSCP value in \"control=%s\"", arg); - return ERROR; - } - } - else - { - *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg); - return ERROR; - } - break; - - case CONTROL_ERROR: - return ERROR; - - case CONTROL_CASEFUL_LOCAL_PART: - deliver_localpart = addr->cc_local_part; - break; - - case CONTROL_CASELOWER_LOCAL_PART: - deliver_localpart = addr->lc_local_part; - break; - - case CONTROL_ENFORCE_SYNC: - smtp_enforce_sync = TRUE; - break; - - case CONTROL_NO_ENFORCE_SYNC: - 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_NO_PIPELINING: - pipelining_enable = FALSE; - break; - - case CONTROL_NO_DELAY_FLUSH: - disable_delay_flush = TRUE; - break; - - case CONTROL_NO_CALLOUT_FLUSH: - disable_callout_flush = TRUE; - break; - - case CONTROL_FAKEDEFER: - case CONTROL_FAKEREJECT: - fake_response = (control_type == CONTROL_FAKEDEFER) ? DEFER : FAIL; - if (*p == '/') - { - uschar *pp = p + 1; - while (*pp != 0) pp++; - fake_response_text = expand_string(string_copyn(p+1, pp-p-1)); - p = pp; - } - else - { - /* Explicitly reset to default string */ - fake_response_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); - 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: - queue_only_policy = TRUE; - break; - - case CONTROL_SUBMISSION: - originator_name = US""; - submission_mode = TRUE; - while (*p == '/') - { - if (Ustrncmp(p, "/sender_retain", 14) == 0) - { - p += 14; - active_local_sender_retain = TRUE; - active_local_from_check = FALSE; - } - else if (Ustrncmp(p, "/domain=", 8) == 0) - { - uschar *pp = p + 8; - while (*pp != 0 && *pp != '/') pp++; - submission_domain = string_copyn(p+8, pp-p-8); - p = pp; - } - /* The name= option must be last, because it swallows the rest of - the string. */ - else if (Ustrncmp(p, "/name=", 6) == 0) - { - uschar *pp = p + 6; - while (*pp != 0) pp++; - submission_name = string_copy(parse_fix_phrase(p+6, pp-p-6, - big_buffer, big_buffer_size)); - p = pp; - } - else break; - } - if (*p != 0) - { - *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg); - return ERROR; - } - break; - - case CONTROL_DEBUG: - while (*p == '/') - { - if (Ustrncmp(p, "/tag=", 5) == 0) - { - uschar *pp = p + 5; - while (*pp != '\0' && *pp != '/') pp++; - debug_tag = string_copyn(p+5, pp-p-5); - p = pp; - } - else if (Ustrncmp(p, "/opts=", 6) == 0) - { - uschar *pp = p + 6; - while (*pp != '\0' && *pp != '/') pp++; - debug_opts = string_copyn(p+6, pp-p-6); - p = pp; - } - } - debug_logging_activate(debug_tag, debug_opts); - break; - - case CONTROL_SUPPRESS_LOCAL_FIXUPS: - suppress_local_fixups = TRUE; - break; - - case CONTROL_CUTTHROUGH_DELIVERY: - if (deliver_freeze) - { - *log_msgptr = string_sprintf("\"control=%s\" on frozen item", arg); - return ERROR; - } - if (queue_only_policy) - { - *log_msgptr = string_sprintf("\"control=%s\" on queue-only item", arg); - return ERROR; - } - cutthrough_delivery = TRUE; + const uschar *p = NULL; + control_type = decode_control(arg, &p, where, log_msgptr); + + /* 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) + { + case CONTROL_AUTH_UNADVERTISED: + allow_auth_unadvertised = TRUE; + break; + + #ifdef EXPERIMENTAL_BRIGHTMAIL + case CONTROL_BMI_RUN: + bmi_run = 1; + break; + #endif + + #ifndef DISABLE_DKIM + case CONTROL_DKIM_VERIFY: + dkim_disable_verify = TRUE; + #ifdef EXPERIMENTAL_DMARC + /* Since DKIM was blocked, skip DMARC too */ + dmarc_disable_verify = TRUE; + dmarc_enable_forensic = FALSE; + #endif + break; + #endif + + #ifdef EXPERIMENTAL_DMARC + case CONTROL_DMARC_VERIFY: + dmarc_disable_verify = TRUE; + break; + + case CONTROL_DMARC_FORENSIC: + dmarc_enable_forensic = TRUE; + break; + #endif + + case CONTROL_DSCP: + if (*p == '/') + { + int fd, af, level, optname, value; + /* If we are acting on stdin, the setsockopt may fail if stdin is not + a socket; we can accept that, we'll just debug-log failures anyway. */ + fd = fileno(smtp_in); + af = ip_get_address_family(fd); + if (af < 0) + { + HDEBUG(D_acl) + debug_printf("smtp input is probably not a socket [%s], not setting DSCP\n", + strerror(errno)); + break; + } + if (dscp_lookup(p+1, af, &level, &optname, &value)) + { + if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0) + { + HDEBUG(D_acl) debug_printf("failed to set input DSCP[%s]: %s\n", + p+1, strerror(errno)); + } + else + { + HDEBUG(D_acl) debug_printf("set input DSCP to \"%s\"\n", p+1); + } + } + else + { + *log_msgptr = string_sprintf("unrecognised DSCP value in \"control=%s\"", arg); + return ERROR; + } + } + else + { + *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg); + return ERROR; + } + break; + + case CONTROL_ERROR: + return ERROR; + + case CONTROL_CASEFUL_LOCAL_PART: + deliver_localpart = addr->cc_local_part; + break; + + case CONTROL_CASELOWER_LOCAL_PART: + deliver_localpart = addr->lc_local_part; + break; + + case CONTROL_ENFORCE_SYNC: + smtp_enforce_sync = TRUE; + break; + + case CONTROL_NO_ENFORCE_SYNC: + 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_NO_PIPELINING: + pipelining_enable = FALSE; + break; + + case CONTROL_NO_DELAY_FLUSH: + disable_delay_flush = TRUE; + break; + + case CONTROL_NO_CALLOUT_FLUSH: + disable_callout_flush = TRUE; + break; + + case CONTROL_FAKEREJECT: + cancel_cutthrough_connection("fakereject"); + case CONTROL_FAKEDEFER: + fake_response = (control_type == CONTROL_FAKEDEFER) ? DEFER : FAIL; + if (*p == '/') + { + const uschar *pp = p + 1; + while (*pp != 0) pp++; + fake_response_text = expand_string(string_copyn(p+1, pp-p-1)); + p = pp; + } + else + { + /* Explicitly reset to default string */ + fake_response_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); + 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; + } + cancel_cutthrough_connection("item frozen"); + break; + + case CONTROL_QUEUE_ONLY: + queue_only_policy = TRUE; + cancel_cutthrough_connection("queueing forced"); + break; + + case CONTROL_SUBMISSION: + originator_name = US""; + submission_mode = TRUE; + while (*p == '/') + { + if (Ustrncmp(p, "/sender_retain", 14) == 0) + { + p += 14; + active_local_sender_retain = TRUE; + active_local_from_check = FALSE; + } + else if (Ustrncmp(p, "/domain=", 8) == 0) + { + const uschar *pp = p + 8; + while (*pp != 0 && *pp != '/') pp++; + submission_domain = string_copyn(p+8, pp-p-8); + p = pp; + } + /* The name= option must be last, because it swallows the rest of + the string. */ + else if (Ustrncmp(p, "/name=", 6) == 0) + { + const uschar *pp = p + 6; + while (*pp != 0) pp++; + submission_name = string_copy(parse_fix_phrase(p+6, pp-p-6, + big_buffer, big_buffer_size)); + p = pp; + } + else break; + } + if (*p != 0) + { + *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg); + return ERROR; + } + break; + + case CONTROL_DEBUG: + while (*p == '/') + { + if (Ustrncmp(p, "/tag=", 5) == 0) + { + const uschar *pp = p + 5; + while (*pp != '\0' && *pp != '/') pp++; + debug_tag = string_copyn(p+5, pp-p-5); + p = pp; + } + else if (Ustrncmp(p, "/opts=", 6) == 0) + { + const uschar *pp = p + 6; + while (*pp != '\0' && *pp != '/') pp++; + debug_opts = string_copyn(p+6, pp-p-6); + p = pp; + } + } + debug_logging_activate(debug_tag, debug_opts); + break; + + case CONTROL_SUPPRESS_LOCAL_FIXUPS: + suppress_local_fixups = TRUE; + break; + + case CONTROL_CUTTHROUGH_DELIVERY: + if (prdr_requested) + /* Too hard to think about for now. We might in future cutthrough + the case where both sides handle prdr and this-node prdr acl + is "accept" */ + *log_msgptr = string_sprintf("PRDR on %s reception\n", arg); + else + { + if (deliver_freeze) + *log_msgptr = US"frozen"; + else if (queue_only_policy) + *log_msgptr = US"queue-only"; + else if (fake_response == FAIL) + *log_msgptr = US"fakereject"; + else + { + if (rcpt_count == 1) cutthrough.delivery = TRUE; + break; + } + *log_msgptr = string_sprintf("\"control=%s\" on %s item", + arg, *log_msgptr); + } + return ERROR; + } break; } - break; #ifdef EXPERIMENTAL_DCC case ACLC_DCC: { /* Seperate the regular expression and any optional parameters. */ - uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size); + const uschar * list = arg; + uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size); /* Run the dcc backend. */ rc = dcc_process(&ss); /* Modify return code based upon the existance of options. */ - while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size)) + while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) != NULL) { if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER) { @@ -3472,7 +3507,7 @@ for (; cb != NULL; cb = cb->next) case ACLC_DOMAINS: rc = match_isinlist(addr->domain, &arg, 0, &domainlist_anchor, - addr->domain_cache, MCL_DOMAIN, TRUE, &deliver_domain_data); + addr->domain_cache, MCL_DOMAIN, TRUE, CUSS &deliver_domain_data); break; /* The value in tls_cipher is the full cipher name, for example, @@ -3505,21 +3540,22 @@ for (; cb != NULL; cb = cb->next) case ACLC_HOSTS: rc = verify_check_this_host(&arg, sender_host_cache, NULL, - (sender_host_address == NULL)? US"" : sender_host_address, &host_data); + (sender_host_address == NULL)? US"" : sender_host_address, + CUSS &host_data); if (host_data != NULL) host_data = string_copy_malloc(host_data); break; case ACLC_LOCAL_PARTS: rc = match_isinlist(addr->cc_local_part, &arg, 0, &localpartlist_anchor, addr->localpart_cache, MCL_LOCALPART, TRUE, - &deliver_localpart_data); + CUSS &deliver_localpart_data); break; case ACLC_LOG_REJECT_TARGET: { int logbits = 0; int sep = 0; - uschar *s = arg; + const uschar *s = arg; uschar *ss; while ((ss = string_nextinlist(&s, &sep, big_buffer, big_buffer_size)) != NULL) @@ -3541,7 +3577,7 @@ for (; cb != NULL; cb = cb->next) case ACLC_LOGWRITE: { int logbits = 0; - uschar *s = arg; + const uschar *s = arg; if (*s == ':') { s++; @@ -3572,21 +3608,29 @@ for (; cb != NULL; cb = cb->next) break; #ifdef WITH_CONTENT_SCAN - case ACLC_MALWARE: + case ACLC_MALWARE: /* Run the malware backend. */ { /* 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); - /* 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; - } - } + const uschar * list = arg; + uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size); + uschar *opt; + BOOL defer_ok = FALSE; + int timeout = 0; + + while ((opt = string_nextinlist(&list, &sep, NULL, 0))) + if (strcmpic(opt, US"defer_ok") == 0) + defer_ok = TRUE; + else if ( strncmpic(opt, US"tmo=", 4) == 0 + && (timeout = readconf_readtime(opt+4, '\0', FALSE)) < 0 + ) + { + *log_msgptr = string_sprintf("bad timeout value in '%s'", opt); + return ERROR; + } + + rc = malware(ss, timeout); + if (rc == DEFER && defer_ok) + rc = FAIL; /* FAIL so that the message is passed to the next ACL */ } break; @@ -3600,8 +3644,8 @@ for (; cb != NULL; cb = cb->next) break; case ACLC_RECIPIENTS: - rc = match_address_list(addr->address, TRUE, TRUE, &arg, NULL, -1, 0, - &recipient_data); + rc = match_address_list((const uschar *)addr->address, TRUE, TRUE, &arg, NULL, -1, 0, + CUSS &recipient_data); break; #ifdef WITH_CONTENT_SCAN @@ -3625,8 +3669,8 @@ for (; cb != NULL; cb = cb->next) break; case ACLC_SENDERS: - rc = match_address_list(sender_address, TRUE, TRUE, &arg, - sender_address_cache, -1, 0, &sender_data); + rc = match_address_list((const uschar *)sender_address, TRUE, TRUE, &arg, + sender_address_cache, -1, 0, CUSS &sender_data); break; /* Connection variables must persist forever */ @@ -3644,11 +3688,12 @@ for (; cb != NULL; cb = cb->next) case ACLC_SPAM: { /* Seperate the regular expression and any optional parameters. */ - uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size); + const uschar * list = arg; + uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size); /* Run the spam backend. */ - rc = spam(&ss); + rc = spam(CUSS &ss); /* Modify return code based upon the existance of options. */ - while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size)) + while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) != NULL) { if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER) { @@ -4121,7 +4166,11 @@ while (acl != NULL) switch(acl->verb) { case ACL_ACCEPT: - if (cond == OK || cond == DISCARD) return cond; + if (cond == OK || cond == DISCARD) + { + HDEBUG(D_acl) debug_printf("end of %s: ACCEPT\n", acl_name); + return cond; + } if (endpass_seen) { HDEBUG(D_acl) debug_printf("accept: endpass encountered - denying access\n"); @@ -4132,17 +4181,26 @@ while (acl != NULL) case ACL_DEFER: if (cond == OK) { + HDEBUG(D_acl) debug_printf("end of %s: DEFER\n", acl_name); acl_temp_details = TRUE; return DEFER; } break; case ACL_DENY: - if (cond == OK) return FAIL; + if (cond == OK) + { + HDEBUG(D_acl) debug_printf("end of %s: DENY\n", acl_name); + return FAIL; + } break; case ACL_DISCARD: - if (cond == OK || cond == DISCARD) return DISCARD; + if (cond == OK || cond == DISCARD) + { + HDEBUG(D_acl) debug_printf("end of %s: DISCARD\n", acl_name); + return DISCARD; + } if (endpass_seen) { HDEBUG(D_acl) debug_printf("discard: endpass encountered - denying access\n"); @@ -4151,11 +4209,19 @@ while (acl != NULL) break; case ACL_DROP: - if (cond == OK) return FAIL_DROP; + if (cond == OK) + { + HDEBUG(D_acl) debug_printf("end of %s: DROP\n", acl_name); + return FAIL_DROP; + } break; case ACL_REQUIRE: - if (cond != OK) return cond; + if (cond != OK) + { + HDEBUG(D_acl) debug_printf("end of %s: not OK\n", acl_name); + return cond; + } break; case ACL_WARN: @@ -4193,7 +4259,7 @@ return FAIL; the name of an ACL followed optionally by up to 9 space-separated arguments. The name and args are separately expanded. Args go into $acl_arg globals. */ static int -acl_check_wargs(int where, address_item *addr, uschar *s, int level, +acl_check_wargs(int where, address_item *addr, const uschar *s, int level, uschar **user_msgptr, uschar **log_msgptr) { uschar * tmp; @@ -4311,10 +4377,10 @@ sender_verified_failed = NULL; ratelimiters_cmd = NULL; log_reject_target = LOG_MAIN|LOG_REJECT; -#ifdef EXPERIMENTAL_PRDR -if (where == ACL_WHERE_RCPT || where == ACL_WHERE_PRDR ) +#ifndef DISABLE_PRDR +if (where == ACL_WHERE_RCPT || where == ACL_WHERE_PRDR) #else -if (where == ACL_WHERE_RCPT ) +if (where == ACL_WHERE_RCPT) #endif { adb = address_defaults; @@ -4355,12 +4421,10 @@ If conn-failure, no action (and keep the spooled copy). switch (where) { case ACL_WHERE_RCPT: -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR case ACL_WHERE_PRDR: #endif - if( rcpt_count > 1 ) - cancel_cutthrough_connection("more than one recipient"); - else if (rc == OK && cutthrough_delivery && cutthrough_fd < 0) + if (rc == OK && cutthrough.delivery && rcpt_count > cutthrough.nrcpt) open_cutthrough_connection(addr); break; @@ -4475,4 +4539,6 @@ FILE *f = (FILE *)ctx; fprintf(f, "-acl%c %s %d\n%s\n", name[0], name+1, Ustrlen(value), value); } +/* vi: aw ai sw=2 +*/ /* End of acl.c */