From a1caa6da6f72e8c5b8b24678e32c4953a26a2b48 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Thu, 21 Mar 2024 23:48:32 +0000 Subject: [PATCH] Option for taint when setting variable under -be --- doc/doc-docbook/spec.xfpt | 5 +++++ doc/doc-txt/NewStuff | 2 ++ src/src/acl.c | 10 +++++----- src/src/exim.c | 4 +++- src/src/functions.h | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index d030a8411..d71d3696f 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -2886,6 +2886,11 @@ available to admin users. The word &"set"& at the start of a line, followed by a single space, is recognised specially as defining a value for a variable. +.new +.cindex "tainted data" "expansion testing" +If the sequence &",t"& is inserted before the space, +the value is marked as tainted. +.wen The syntax is otherwise the same as the ACL modifier &"set ="&. .cmdopt -bem <&'filename'&> diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 2439b3137..58ab945be 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -18,6 +18,8 @@ Version 4.98 4. The recipients_max main option is now expanded. + 5. Setting variables for "exim -be" can set a tainted value. + Version 4.97 ------------ diff --git a/src/src/acl.c b/src/src/acl.c index f4d65464e..29441dfc1 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -800,7 +800,7 @@ return TRUE; static BOOL acl_data_to_cond(const uschar * s, acl_condition_block * cond, - const uschar * name, uschar ** error) + const uschar * name, BOOL taint, uschar ** error) { if (*s++ != '=') { @@ -809,7 +809,7 @@ if (*s++ != '=') return FALSE;; } Uskip_whitespace(&s); -cond->arg = string_copy(s); +cond->arg = taint ? string_copy_taint(s, GET_TAINTED) : string_copy(s); return TRUE; } @@ -959,7 +959,7 @@ while ((s = (*func)())) "endpass" has no data */ if (c != ACLC_ENDPASS) - if (!acl_data_to_cond(s, cond, name, error)) return NULL; + if (!acl_data_to_cond(s, cond, name, FALSE, error)) return NULL; } return yield; @@ -4941,7 +4941,7 @@ fprintf(f, "acl%c %s %d\n%s\n", name[0], name+1, Ustrlen(value), value); uschar * -acl_standalone_setvar(const uschar * s) +acl_standalone_setvar(const uschar * s, BOOL taint) { acl_condition_block * cond = store_get(sizeof(acl_condition_block), GET_UNTAINTED); uschar * errstr = NULL, * log_msg = NULL; @@ -4951,7 +4951,7 @@ int e; cond->next = NULL; cond->type = ACLC_SET; if (!acl_varname_to_cond(&s, cond, &errstr)) return errstr; -if (!acl_data_to_cond(s, cond, US"'-be'", &errstr)) return errstr; +if (!acl_data_to_cond(s, cond, US"'-be'", taint, &errstr)) return errstr; if (acl_check_condition(ACL_WARN, cond, ACL_WHERE_UNKNOWN, NULL, 0, &endpass_seen, &errstr, &log_msg, &e) != OK) diff --git a/src/src/exim.c b/src/src/exim.c index c591ee60c..3170bef98 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -1704,8 +1704,10 @@ if (isupper(big_buffer[0])) if (macro_read_assignment(big_buffer)) printf("Defined macro '%s'\n", mlast->name); } +else if (Ustrncmp(big_buffer, "set,t ", 6) == 0) + printf("%s\n", acl_standalone_setvar(big_buffer+6, TRUE)); else if (Ustrncmp(big_buffer, "set ", 4) == 0) - printf("%s\n", acl_standalone_setvar(big_buffer+4)); + printf("%s\n", acl_standalone_setvar(big_buffer+4, FALSE)); else if ((s = expand_string(big_buffer))) printf("%s\n", CS s); else printf("Failed: %s\n", expand_string_message); diff --git a/src/src/functions.h b/src/src/functions.h index 77323a5c1..0e657d7c4 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -103,7 +103,7 @@ extern acl_block *acl_read(uschar *(*)(void), uschar **); extern int acl_check(int, const uschar *, uschar *, uschar **, uschar **); extern uschar *acl_current_verb(void); extern int acl_eval(int, uschar *, uschar **, uschar **); -extern uschar *acl_standalone_setvar(const uschar *); +extern uschar *acl_standalone_setvar(const uschar *, BOOL); extern tree_node *acl_var_create(uschar *); extern void acl_var_write(uschar *, uschar *, void *); -- 2.30.2