Alan T. DeKok [Fri, 11 Apr 2025 12:03:21 +0000 (08:03 -0400)]
Update xlat expression parser to avoid a bounce through tmpls
the expression parser now calls the xlat_tokenize_word(). That
function returns xlat groups for strings, and not tmpls.
Update the %cast() function to always create its arguments as groups.
This helps when "foo%{User-Name}" is now parsed as an xlat group,
and not as an xlat which is pointing to a tmpl
xlat_process_arg_list() now calls a separate function to escape
and stringify its output
Add "is_argv" flag to xlat_exp_head_t. This tells the xlat eval
code to NOT concatenate strings, as the function argument parser
will do that, with escaping.
various cleanups in xlat_tokenize_word()
Hoist constant strings after calling xlat_tokenize_input(). This
code should arguably be moved to xlat_tokenize_input().
xlat_argv tests now also print strings with the enclosing quotes.
Nick Porter [Fri, 11 Apr 2025 16:28:51 +0000 (17:28 +0100)]
We never incref on the pythonconf_dict
The reference count is increased when the dictionary is added to the
module, and automatically removed when the module is freed as the
interpreter is freed.
Nick Porter [Fri, 11 Apr 2025 16:14:34 +0000 (17:14 +0100)]
With m_size = -1, freeradius module doesn't clear up correctly
Each module instance is getting it's own copy of the module, whereas
m_size = -1 implies it is global and causes a crash on exit when there
are multiple interpreters.
Alan T. DeKok [Wed, 9 Apr 2025 20:40:32 +0000 (16:40 -0400)]
remove bounce through tmpl code for %{...}
Instead, we create an XLAT_GROUP to hold the child xlat.
We then also create a "hoist" flag, which only exists for a
group node, and isn't in the flags.
update the debug printer to match.
Update the evaluation code to look for the "hoist' flag,
and then hoist the result instead of creating a value-box group.
Note that the result may be empty. In which case nothing is
added to the output dcursor. For xlat function arguments, this
highlights the need to have each argument expanded into its own
group.
Alan T. DeKok [Tue, 8 Apr 2025 22:29:12 +0000 (18:29 -0400)]
we don't allow unresolved xlats
it helps to return errors when there are error cases.
Disallow "foo." for list existence. Arguably "foo.[*]" is better.
the xlat condition / expression parser already replaces a bare
existence check with a %exists() wrapper. So the run-time code
doesn't need to expand the entire thing.
Alan T. DeKok [Sun, 6 Apr 2025 20:09:12 +0000 (16:09 -0400)]
we no longer need a macro for escape
rearrange the code so that the escaping is done first.
but we do assert that the value-boxes are not groups, in preparation
for updating the expression parser. Those changes mean that a
string which contains an xlat expansion will result in a group
of the component pieces. We can then escape each component piece
individually, before concatenating them into the resulting string.
Alan T. DeKok [Sat, 5 Apr 2025 14:51:22 +0000 (10:51 -0400)]
concatenate function arguments when evaluating
the edit code already does this. The function argument code
did not. The result was that the functions were being passed
value-box lists / groups, when the intention of the admin was
to pass in one quoted string.
The xlat expression parser "fixed" this issue by adding a cast
when it parsed strings. But that cast would then encapsulate the
function arguments into another function call. That either
prevented the escaping of strings, or did the concatentation to
string which then mashed it to SAFE_FOR_NONE.
The final string would then be escaped, which is not what the
admin intended.
Alan T. DeKok [Sat, 29 Mar 2025 23:20:16 +0000 (19:20 -0400)]
track safety of regex data
so that if we do regex captures of something which is SAFE_FOR_SQL,
the resulting string is also SAFE_FOR_SQL.
There are odd cases where this _might_ be wrong, such as when
the capture text crosses a quoted string boundary. But that is
arguably the fault of the admin who created the offending regex,
and decided to use it in an unsafe manner.
Alan T. DeKok [Sat, 29 Mar 2025 16:55:58 +0000 (12:55 -0400)]
allow debug level to be changed dynamically
%debug(4) didn't actually do anything, because it changed
request->log.lvl. And the log_request() function didn't check
that.
Update the code to log the message if either the _entire_ request
is marked as "log at this level" or if this particular destination
is marked as "log at this level"