On 10/02/2010 11:05 AM, Brian Candler wrote:
Why don't you just do whatever "if()" logic before adding the attributes?
It's complicated :-)
Partly it's policy. We configure as much of this logic in users files as
possible, because they can be updated without needing to restart radiusd.
The obvious solution to this is SQL, but you're already planning on
moving to that.
But in future it will be a necessity. The project I'm working on involves
authenticating users based on some attribute which identifies their physical
location, not their User-Name. So decisions you might have made in the past
solely based on realm and NAS-IP (e.g. tunnel to X) have to be made after a
database lookup.
We do something similar with per-location MAC auth; when the request
comes in, the Calling-Station-Id and NAS-IP-Address are fed into an SQL
stored procedure that does the heavy lifting; a machines get the
"closest" match VLAN for the given switch, based on a mapping of IPv4
subnets to vlans, and MAC to IP addresses and fallback zones/vlans.
My point being, the logic is all done in the lookup (but see below for
how I also permit overriding without attribute removal)
That database lookup may add reply attributes, which will be needed by the
terminating LNS, but not when tunnel switching. So if the database
identifies the user as category X, *and* the request comes from NAS-IP Y,
then we have to strip the reply attributes and replace with tunnelling ones.
The approach I take is to have the database lookup add a local
(non-wire) attribute set to the request (not reply) pairs. I then copy
that (conditionally) into the reply. It more or less works like so:
authorize {
# do the SQL lookup
update control {
Tmp-String-0 := "%{sql:select vlan||','||zone from proc('...')}"
}
if (control:Tmp-String-0 =~ /(.+),(.+)/) {
update request {
MyVlan = "%{0}"
MyZone = "%{1}"
}
}
else {
# SQL failed?
reject
}
# permit manual overrides
override_files
if (ok) {
# do nothing more
}
# obviously here you could have elif() statements
# that generate reply pairs in many different ways
else {
update reply {
Tunnel-Private-Group-Id = "%{MyVlan}"
}
}
}
"override_files" is just a "files" module in which we can put things
which the database module lookup can't (or shouldn't) handle, like
temporary testing hacks and such. Since we're using a "files" module for
this, the attribute I add from the database need to go into the request
pairs, so I can do things like:
DEFAULT NAS-IP-Address == ..., MyVlan == 1234
Vendor-Thing = "tagged-vlan=%{MyVlan}"
...and other such junk.
The point of all this is that you can add attributes into the request or
control pairs, or non-wire attributes into the reply, and then do
conditional logic on those, and not have to worry about stripping them
out - for request/control pairs, obviously because they're not sent in
the reply, and for non-wire reply pairs, because they're not sent on the
wire.
By "non-wire" I mean anything with an attribute number >255 - such as
Tmp-String-0, or any other attributes you care to define in a local
dictionary (FreeRadius reserves 3000-3999 for this purpose)
HTH
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html