Using configuration items in strings

Alan DeKok aland at
Sat Feb 15 16:26:17 CET 2014

Arran Cudbard-Bell wrote:
> Hm, no. Using RFC terms, and assuming were going for optimum efficiency:
> if (${foo})
> MUST NOT be optimised away, it is a attribute or rcode check with the value of the CONF_PAIR ${foo}

  I'm not sure what you mean by "optimized away".  ${foo} gets replaced
with the value of configuration item 'foo', by the configuration file
reader.  This happens *before* any analysis is done of the condition.


	foo = 0
	if (${foo}) { ...


	if (0) { ...

  are identical.

  It sounds like your analysis is mixing up the two passes.

1) string substitution ${foo} --> value of configuration item "foo"

2) compilation to string xlat, attribute reference, etc.

> if ("${foo}") 
> SHOULD be optimised away, it is an XLAT expansion only containing string literals.

  Only if the string inside of the double quotes contains a % character.

> Where ${foo} -> '%{User-Name}'
> MUST NOT be optimised away, it is an XLAT expansion containing an attribute reference.

  Be careful with the single quotes.  %{User-Name} is an xlat saying
"the value of the User-Name attribute".  '%{User-Name}' is a
single-quoted string with contents %{User-Name}.  The contents are a
*static* string, and aren't dynamically expanded.

> However, actually testing the code it seems optimisation isn't working as expected...
> Where ${foo} -> 'User-Name'

  Remember, this is *dumb* string substitution.

> authorize {
>         if (!'${foo}') {
>                 ok  
>         }   

  That's a single quoted string with static contents User-Name.  Note
that the ${foo} expansion is done inside of single quoted strings.

  Note also that when the configuration file code parses:

foo = 'User-Name'

  Then foo has a data type of "literal string", and a value of
User-Name.  *Without* the quotes.  The configuration file string
expansion is done by copying the values, not by printing the CONF_PAIRs.

  Otherwise, it would do:

foo = 'User-Name'

	if (!'${foo}') {

expands ${foo} to 'User-Name', and gets

	if (!''User-Name'') {

which would be a parse error.

  The single / double-quotes for configuration items are intended to let
the configuration file parser correctly parse the values.  Once the
values are parsed, the strings are static.  They don't need escaping,
and they don't need quotes added.

>         if (!"${foo}") {
>                 ok  
>         }   

  That's a double-quoted string, with static contents User-Name (WITHOUT
the single quotes!).  Since there's no % in the string, the dynamic
expansion is just a string copy.

>         if (!${foo}) {
>                 ok  
>         }   

  That's an attribute reference of User-Name.

>         if (!('${foo}' == 'bar')) {
>                 ok  
>         }  
> }

  That's again a static string comparison of 'User-Name' to 'bar'.
They're different, and will always be different.

> Ready to process requests.
> rad_recv: Access-Request packet from host port 51784, id=52, length=38
> 	User-Password = 'foo'
> (0) # Executing section authorize from file /usr/local/freeradius-3.0.x/etc/raddb/sites-enabled/default
> (0)   authorize {
> (0)   ? if (!'User-Name') 
> (0)   ? if (!'User-Name')  -> FALSE

  Yes.  'User-Name' is a non-NULL string, so it's always TRUE.  !TRUE is

> (0)   ? if (!"User-Name")  -> FALSE

  The same applies here.

> (0)   ? if (!User-Name)  -> TRUE

  Here, User-Name is an attribute reference.  The packet you sent didn't
include a User-Name.  So the check for existence of User-Name is FALSE,
and !FALSE is TRUE.

> (0)   ? if (!('User-Name' == 'bar'))  -> TRUE

  That's correct.  The string 'User-Name' is not the same as the string
'bar'.  So that evaluates to FALSE.  And !FALSE is TRUE.

> But I may be miss-understanding on how it's meant to operate.

  The string substitution for ${var} is very simple, and is *completely*
independent of the step which parses conditions.  The "parse condition"
step just sees text strings.  All of the ${foo} magic has gone away.

  Alan DeKok.

More information about the Freeradius-Users mailing list