Re: Concatenating/inserting strings with backslashes

2012-11-10 Thread Alan DeKok
Brian Candler wrote:
> Here's something weird. I'm trying to concatenate some strings which contain
>   (i.e.  not a newline).

  Well... that's all pretty hacky.  It's made worse by Reply-Message
being automatically expanded, whereas other attributes aren't.  Try your
tests below using Filter-Id, and they will be different.

  The server has grown over the years in a fairly ad-hoc way.  I welcome
suggestions for sanitizing how it deals with string.

  Alan DeKok.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html


RE: Concatenating/inserting strings with backslashes

2012-11-09 Thread Brian Julin


> Brian Candler wrote
> 
> > try:
> >
> > if (%{reply:Reply-Message} =~ /(.*)/) {
> >update reply {
> >  Reply-Message = "stuff %{1}"
> >}
> > }
> 
> Nice idea, but it appears to suffer the same expansion problem.
> 
> As you have written it gives this error:
> 
>   Bare %{...} is invalid in condition at: %{reply:Reply-Message} =~ /(.*)/)
> 
> Adding the double quotes:

Oh right.

I usually do this with e.g. User-Name without having to specify the attribute 
list
explicitly; I forget whether syntax works to do that with a raw variable.
I know outer.VarName works raw, so maybe just reply:Reply-Message
without the braces or quotes?

-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html


Re: Concatenating/inserting strings with backslashes

2012-11-09 Thread Brian Candler
> try:
> 
> if (%{reply:Reply-Message} =~ /(.*)/) {
>update reply {
>  Reply-Message = "stuff %{1}"
>}
> }

Nice idea, but it appears to suffer the same expansion problem.

As you have written it gives this error:

  Bare %{...} is invalid in condition at: %{reply:Reply-Message} =~ /(.*)/)

Adding the double quotes:

update reply {
  Reply-Message := "foo"
}
if ("%{reply:Reply-Message}" =~ /(.*)/) {
  update reply {
Reply-Message := "%{1}nbar"
  }
}  
if ("%{reply:Reply-Message}" =~ /(.*)/) {
  update reply {
Reply-Message := "%{1}nbaz"
  }
}

This gives foo  bar  baz

update reply {
  Reply-Message := "foo"
}
if ("%{reply:Reply-Message}" =~ /(.*)/) {
  update reply {
Reply-Message := "%{1}nbar"
  }
}
if ("%{reply:Reply-Message}" =~ /(.*)/) {
  update reply {
Reply-Message := "%{1}nbaz"
  }
}

This gives foo  bar   baz

Regards,

Brian.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html


Re: Concatenating/inserting strings with backslashes

2012-11-09 Thread Phil Mayers

On 09/11/12 15:39, Brian Candler wrote:

Here's something weird. I'm trying to concatenate some strings which contain
  (i.e.  not a newline).


Uh oh... here be dragons!


In a normal string literal, I have to enter four backslashes:

update reply {
 Reply-Message := "anb"
}

("\\n" gives a newline, "\\\n" gives backslash followed by newline)


Yeah; I think there is a similar thing happening here to the regexp 
stuff I discussed on -devel recently.


I think what happens in the code is this:

 1. lib/token.c:gettoken loads the config file and performs backslash 
processing on any quoted strings


 2. conffile.c:cf_pairtovp loads the VP update list at config load 
time, and sets the "do_xlat" flag on any that are double-quoted


 3. modcall.c:modcall calls radius_update_attrlist

 4. evaluate.c:radius_update_attrlist checks the "do_xlat" flag on the 
VP, which was set at config load, and calls expand_string (which calls 
radius_xlat) followed by pairparsevalue.



The net effect is that:

update x {
  Foo = "an"
}

...is de-escaped many times:

 * into "an" by the gettoken / config file loader
 * into "an" by radius_xlat
 * into "a" by pairparsevalue (on the result of radius_xlat)

This kind of thing is pretty common - exim has a similar problem. It's 
difficult to know what to do about it in a manner that's universally 
satisfactory.


One solution is to not process "\x" anywhere except loading from config 
files, but that's likely a very significant backwards compatibility 
break... you also might *want* to provide a way for people to interpret 
escapes again (though this can be done with an xlat e.g.


"%{unescape:%{something-that-returns-backslash-n}}" == ""

Others options exist. Personally I find the existing behaviour quite 
surprising, but it's also something I very seldom run into, so don't 
worry too much about.

-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html


RE: Concatenating/inserting strings with backslashes

2012-11-09 Thread Brian Julin

> Brian Candler writes:

> Or is there another way I can concatenate strings, which doesn't involve
> expanding them into another string?

The workaround I've used for this is to feed the value through a regexp
match to get it into %{1}, which does not seem to be subject to unescaping.

try:

if (%{reply:Reply-Message} =~ /(.*)/) {
   update reply {
 Reply-Message = "stuff %{1}"
   }
}
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html


Concatenating/inserting strings with backslashes

2012-11-09 Thread Brian Candler
Here's something weird. I'm trying to concatenate some strings which contain
  (i.e.  not a newline).

In a normal string literal, I have to enter four backslashes:

update reply {
Reply-Message := "anb"
}

("\\n" gives a newline, "\\\n" gives backslash followed by newline)

But when I try to insert one string into another it goes completely haywire.

update reply {
Reply-Message := "foonbar"
}
update reply {
Reply-Message := "%{reply:Reply-Message}nbaz"
}

This gives me "foo"  "bar"  "baz". That is, even the
second n is being collapsed into a newline!

Some more test cases:

update reply {
Reply-Message := "foonbar"
}
update reply {
Reply-Message := "quxnbaz"
}

correctly gives me "qux"   "baz"

update reply {
Reply-Message := "foonbar"
}
update reply {
Reply-Message := "%{Wibble:-qux}nbaz"
}

gives me  "baz". In fact, I need *eight* backslashes to get a
literal backslash here:

Reply-Message := "%{Wibble:-qux}nbaz"

So somehow, the presence of a string expansion within a string affects the
interpretation of subsequent backslashes within that string.

Now, this works:

update reply {
Reply-Message := "foonbar"
}
update reply {
Reply-Message := "%{reply:Reply-Message}nbaz"
}

But then if I do another layer of string insertion they get translated to
newlines again.

update reply {
Reply-Message := "foonbar"
}
update reply {
Reply-Message := "%{reply:Reply-Message}nbaz"
}
update reply { 
Reply-Message := "%{reply:Reply-Message}" 
} 

This seems pretty broken to me, but if someone would care to explain how to
deal with it, please do.

Or is there another way I can concatenate strings, which doesn't involve
expanding them into another string?

Thanks,

Brian.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html