Background:

  We're using FreeRADIUS-2.0.3 with an OpenLDAP backend, on two separate
systems for authentication and authorization of users to our wireless
network and a lesser-used VPN service.  I would like to be able to modify
the LDAP query filter based on (for example) which NAS device sent the
RADIUS request so that (again, for example) a different filter might be
used to search for wireless users than for VPN users.

In an effort to be able to setup a "dynamic" LDAP query filter, I have
tried adding a string-type attribute to our local dictionary file,
to hold the filter that would be updated on-the-fly:

 ATTRIBUTE     CU-LDAP-Filter          3000    string

The radiusd.conf file then has ldap module instances (one per LDAP
server) with the following reference to this attribute:

        ldap ldap_host1 {
                server = "ldap_host1"
                identity = "cn=...,ou=...,dc=concordia,dc=ca"
                password = "**SANITIZED**"
                basedn = "ou=people,dc=concordia,dc=ca"
                filter = "%{CU-LDAP-Filter}"
                base_filter = "(objectclass=ConcordiaPerson)"
                ...
        }

        ldap ldap_host2 {
                server = "ldap_host2"
                identity = "cn=...,ou=...,dc=concordia,dc=ca"
                password = "**SANITIZED**"
                basedn = "ou=people,dc=concordia,dc=ca"
                filter = "%{CU-LDAP-Filter}"
                base_filter = "(objectclass=ConcordiaPerson)"
                ...
        }

I'm presently testing with the radeapclient client (on localhost), so am
testing with the following configured into sites-enabled/default:

   authorize {
           ...
           switch "%{NAS-IP-Address}" {
               case 192.168.198.20 {
                   # test
                   update control {
                      CU-LDAP-Filter = 
"(&(cn=%{%{Stripped-User-Name}:-%{User-Name}})(***LDAP QUERY1 TRIMMED FOR 
BREVITY***))"
                   }
               }
               case 127.0.0.1 {
                   # test
                   update control {
                      CU-LDAP-Filter = 
"(&(cn=%{%{Stripped-User-Name}:-%{User-Name}})(***LDAP QUERY2 TRIMMED FOR 
BREVITY***))"
                   }
               }
               ...
               case {
                  # default
                  noop
               }
           }

           if ("%{CU-LDAP-Filter}" != "") {
               redundant-load-balance {
                  ldap_host1
                  ldap_host2
               }
           }
           ...
   }

The LDAP query filters, though not included above (these things are quite
long and site-specific anyway) are known to work, as they're copied from
our currently in-production configuration that is selecting the ldap
module instance based on the NAS-IP-Address (ie. if NAS-IP-Address is
the VPN server we call the ldap_vpn module which is configured with an
appropriate filter, else we call the ldap_wireless module which is also
appropriately configured).  The present setup works, but based on what
I'm reading it would give is a much more flexible and fault-tolerant
(and dare-I-say, more manageable?) setup if I could get the LDAP module
instances configured into a redundant-load-balance stanza, with a
dynamically determined LDAP query filter (so that if one LDAP server is
unavailable, one or more others could be tried instead, instead of
having a hard-coded query to specific LDAP servers for each service).

I hope I'm making sense so far ...

The following command is issued to test:

   radeapclient -x localhost:1815 auth testing123 << END_OF_EAP
   User-Name = "j_doe"
   Cleartext-Password = "**SANITIZED**"
   NAS-IP-Address = 192.168.198.20
   NAS-Port-Type = "Wireless-802.11"
   EAP-Code = Response
   EAP-Id = 210
   EAP-Type-Identity = "j_doe"
   Message-Authenticator = 0x00
   NAS-Port = 0
   END_OF_EAP

Radiusd, running in debug mode shows the following (config-file parsing
output skipped;  it is not showing any errors at all, so although the
configuration I show above may not be producing the intended result, it
at least seems syntactically correct):

   Listening on authentication address * port 1815
   Listening on accounting address * port 1816
   Listening on proxy address * port 1817
   Ready to process requests.
           User-Name = "j_doe"
           NAS-IP-Address = 192.168.198.20
           NAS-Port-Type = Wireless-802.11
           Message-Authenticator = 0x8499bae7c162d5f0ef2e587fdb9086a0
           NAS-Port = 0
           EAP-Message = 0x02d200080173796c
   +- entering group authorize
   ++[preprocess] returns ok
   ++[chap] returns noop
   ++[mschap] returns noop
       rlm_realm: No '@' in User-Name = "j_doe", looking up realm NULL
       rlm_realm: No such realm "NULL"
   ++[suffix] returns noop
     rlm_eap: EAP packet type response id 210 length 8
     rlm_eap: No EAP Start, assuming it's an on-going EAP conversation
   ++[eap] returns updated
   ++[unix] returns notfound
   ++[files] returns noop
           expand: %{NAS-IP-Address} -> 192.168.198.20
   ++- entering switch %{NAS-IP-Address}
   +++- entering case 192.168.198.20
           expand: %{Stripped-User-Name} ->
           expand: %{User-Name} -> j_doe
           expand: (&(cn=%{%{Stripped-User-Name}:-%{User-Name}})**LDAP QUERY1 FILTER 
TRIMMED**) -> (&(cn=j_doe)**LDAP QUERY1 FILTER TRIMMED**)
   ++++[control] returns noop
   +++- case 192.168.198.20 returns noop
   ++- switch %{NAS-IP-Address} returns noop
   ++? if ("%{CU-LDAP-Filter}" != "")
           expand: %{CU-LDAP-Filter} ->
   ? Evaluating ("%{CU-LDAP-Filter}" != "") -> FALSE
   ++? if ("%{CU-LDAP-Filter}" != "") -> FALSE
   ++[expiration] returns noop
   ++[logintime] returns noop
   rlm_pap: WARNING! No "known good" password found for the user.  
Authentication may fail because of this.
   ++[pap] returns noop
     rad_check_password:  Found Auth-Type EAP
   auth: type "EAP"
   +- entering group authenticate
     rlm_eap: EAP Identity
     rlm_eap: processing type tls
     rlm_eap_tls: Initiate
     rlm_eap_tls: Start returned 1
     rlm_eap: RT Modif EAP-Type = 21 EAP-LENGTH = 1
   ++[eap] returns handled
           EAP-Message = 0x01d300061520
           Message-Authenticator = 0x00000000000000000000000000000000
           State = 0x1c870d031c541859b55d17dd8af5914a
   Finished request 0.
   Going to the next request
   Waking up in 4.9 seconds.
   Cleaning up request 0 ID 232 with timestamp +4
   Ready to process requests.


Note that of the above, I believe the following is relevant to my
question:

           expand: %{NAS-IP-Address} -> 192.168.198.20
   ++- entering switch %{NAS-IP-Address}
   +++- entering case 192.168.198.20
           expand: %{Stripped-User-Name} ->
           expand: %{User-Name} -> j_doe
           expand: (&(cn=%{%{Stripped-User-Name}:-%{User-Name}})**LDAP QUERY1 FILTER 
TRIMMED**) -> (&(cn=j_doe)**LDAP QUERY1 FILTER TRIMMED**)
   ++++[control] returns noop
   +++- case 192.168.198.20 returns noop
   ++- switch %{NAS-IP-Address} returns noop
   ++? if ("%{CU-LDAP-Filter}" != "")
           expand: %{CU-LDAP-Filter} ->
   ? Evaluating ("%{CU-LDAP-Filter}" != "") -> FALSE
   ++? if ("%{CU-LDAP-Filter}" != "") -> FALSE

This corresponds to the following from the "authorize" section in my
sites-enabled/default file:

           switch "%{NAS-IP-Address}" {
               case 192.168.198.20 {
                   # test
                   update control {
                      CU-LDAP-Filter = 
"(&(cn=%{%{Stripped-User-Name}:-%{User-Name}})(***LDAP QUERY TRIMMED FOR 
BREVITY***))"
                   }
               }
           }

We see that the line where I intend to assign a value to CU-LDAP-Filter
is indeed encountered and the variables referred to in that line are
expanded correctly, but it seems as though the assignment to
CU-LDAP-Filter isn't done:  if ("%{CU-LDAP-Filter}" != "") is evaluated
as "FALSE".

I suspect that my "update" statement is likely incorrect, since the only
mention of it in the debug output is:

   ++++[control] returns noop

Can anyone help me with this?  I've read as much of the relevant
documentation as I'm aware exists, especially "man unlang" without which
I certainly wouldn't have gotten even this far, but I'd be very grateful
if someone could point me to further documentation that would help with
what I'm trying to do ...

Thanks ...

--
----------------------------------------------------------------------
Sylvain Robitaille                              [EMAIL PROTECTED]

Systems and Network analyst                       Concordia University
Instructional & Information Technology        Montreal, Quebec, Canada
----------------------------------------------------------------------
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

Reply via email to