X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/5032d1cf500b102849d9a47867fbb7b34d871683..93a6fce2ebf117f490d7ee11f066f75280d32386:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index 06c1c494c..69db5cda7 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -802,7 +802,7 @@ static uschar *ratelimit_option_string[] = { /* Enable recursion between acl_check_internal() and acl_check_condition() */ -static int acl_check_wargs(int, address_item *, uschar *, int, uschar **, +static int acl_check_wargs(int, address_item *, const uschar *, int, uschar **, uschar **); @@ -1049,9 +1049,9 @@ Returns: nothing */ static void -setup_header(uschar *hstring) +setup_header(const uschar *hstring) { -uschar *p, *q; +const uschar *p, *q; int hlen = Ustrlen(hstring); /* Ignore any leading newlines */ @@ -1059,14 +1059,24 @@ while (*hstring == '\n') hstring++, hlen--; /* An empty string does nothing; ensure exactly one final newline. */ if (hlen <= 0) return; -if (hstring[--hlen] != '\n') hstring = string_sprintf("%s\n", hstring); -else while(hstring[--hlen] == '\n') hstring[hlen+1] = '\0'; +if (hstring[--hlen] != '\n') + q = string_sprintf("%s\n", hstring); +else if (hstring[hlen-1] == '\n') + { + uschar * s = string_copy(hstring); + while(s[--hlen] == '\n') + s[hlen+1] = '\0'; + q = s; + } +else + q = hstring; /* Loop for multiple header lines, taking care about continuations */ -for (p = q = hstring; *p != 0; ) +for (p = q; *p != 0; ) { - uschar *s; + const uschar *s; + uschar * hdr; int newtype = htype_add_bot; header_line **hptr = &acl_added_headers; @@ -1114,14 +1124,14 @@ for (p = q = hstring; *p != 0; ) if (*s == ':' || !isgraph(*s)) break; } - s = string_sprintf("%s%.*s", (*s == ':')? "" : "X-ACL-Warn: ", (int) (q - p), p); - hlen = Ustrlen(s); + hdr = string_sprintf("%s%.*s", (*s == ':')? "" : "X-ACL-Warn: ", (int) (q - p), p); + hlen = Ustrlen(hdr); /* See if this line has already been added */ while (*hptr != NULL) { - if (Ustrncmp((*hptr)->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); } @@ -1662,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 }, @@ -1726,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 = '/'; @@ -1750,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; @@ -1783,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 @@ -1911,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; @@ -2239,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; @@ -2324,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; @@ -2853,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; @@ -2979,7 +2992,6 @@ 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 = -'/'; @@ -2987,7 +2999,7 @@ int sep = -'/'; 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 @@ -3126,268 +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_FAKEREJECT: - cancel_cutthrough_connection("fakereject"); - case CONTROL_FAKEDEFER: - 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; - } - cancel_cutthrough_connection("item frozen"); - break; + const uschar *p = NULL; + control_type = decode_control(arg, &p, where, log_msgptr); - case CONTROL_QUEUE_ONLY: - queue_only_policy = TRUE; - cancel_cutthrough_connection("queueing forced"); - break; + /* Check if this control makes sense at this time */ - 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; + 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; + } - 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; + 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_SUPPRESS_LOCAL_FIXUPS: - suppress_local_fixups = TRUE; - 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_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(US"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"; + 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 (rcpt_count == 1) cutthrough.delivery = TRUE; - break; + 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); } - *log_msgptr = string_sprintf("\"control=%s\" on %s item", - arg, *log_msgptr); + return ERROR; } - 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) { @@ -3491,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, @@ -3524,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) @@ -3560,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++; @@ -3594,12 +3611,13 @@ for (; cb != NULL; cb = cb->next) 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); + 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(&arg, &sep, NULL, 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 @@ -3626,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 @@ -3651,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 */ @@ -3670,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) { @@ -4240,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;