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

Reply via email to