Re: RADIUS with LDAP: changing LDAP filter based on RADIUS request

2008-06-10 Thread Sylvain Robitaille


On Mon, 9 Jun 2008, Ivan Kalik wrote:


man unlang - attribute lists.

***
The list: prefix is optional, and if omitted, is assumed to refer
to the request list.
***


Ah yes ... That helps a lot.  Thank you.

However, having fixed references to %{CU-LDAP-Filter} so they now refer
to %{control:CU-LDAP-Filter} (since I've assigned a value to that
attribute in an update control statement), I see now that it does
indeed refer to the value I've set, but by the time that's handed to
rlm_ldap, punctuation characters have been replaced with hexadecimal
(escape) representations:

...
+++- entering case 192.168.198.20
expand: %{Stripped-User-Name} -
expand: %{User-Name} - j_doe
expand: 
((cn=%{%{Stripped-User-Name}:-%{User-Name}})(|(memberOf=cn=role_active_emp,ou=portal_role,ou=Groups,dc=concordia,dc=ca)(memberOf=cn=role_faculty,ou=portal_role,ou=Groups,dc=concordia,dc=ca)))
 - 
((cn=j_doe)(|(memberOf=cn=role_active_emp,ou=portal_role,ou=Groups,dc=concordia,dc=ca)(memberOf=cn=role_faculty,ou=portal_role,ou=Groups,dc=concordia,dc=ca)))
[control] returns noop
+++- case 192.168.198.20 returns noop
++- switch %{NAS-IP-Address} returns noop
++? if (%{control:CU-LDAP-Filter} != )
expand: %{control:CU-LDAP-Filter} - 
((cn=j_doe)(|(memberOf=cn=role_active_emp,ou=portal_role,ou=Groups,dc=concordia,dc=ca)(memberOf=cn=role_faculty,ou=portal_role,ou=Groups,dc=concordia,dc=ca)))
? Evaluating (%{control:CU-LDAP-Filter} != ) - TRUE
++? if (%{control:CU-LDAP-Filter} != ) - TRUE
++- entering if (%{control:CU-LDAP-Filter} != )
+++- entering redundant-load-balance group redundant-load-balance
rlm_ldap: - authorize
rlm_ldap: performing user authorization for j_doe
expand: %{control:CU-LDAP-Filter} - 
\28\28cn\3dj_doe\29\28|\28memberOf\3dcn\3drole_active_emp\2cou\3dportal_role\2cou\3dGroups\2cdc\3dconcordia\2cdc\3dca\29\28memberOf\3dcn\3drole_faculty\2cou\3dportal_role\2cou\3dGroups\2cdc\3dconcordia\2cdc\3dca\29\29\29
expand: ou=people,dc=concordia,dc=ca - ou=people,dc=concordia,dc=ca
rlm_ldap: ldap_get_conn: Checking Id: 0
rlm_ldap: ldap_get_conn: Got Id: 0
rlm_ldap: attempting LDAP reconnection
rlm_ldap: (re)connect to host1:389, authentication 0
rlm_ldap: bind as cn=rad_admin,ou=AdminRoles,dc=concordia,dc=ca/**SANITIZED** 
to host1:389
rlm_ldap: waiting for bind result ...
rlm_ldap: Bind was successful
rlm_ldap: performing search in ou=people,dc=concordia,dc=ca, with filter 
\28\28cn\3dj_doe\29\28|\28memberOf\3dcn\3drole_active_emp\2cou\3dportal_role\2cou\3dGroups\2cdc\3dconcordia\2cdc\3dca\29\28memberOf\3dcn\3drole_faculty\2cou\3dportal_role\2cou\3dGroups\2cdc\3dconcordia\2cdc\3dca\29\29\29
rlm_ldap: ldap_search() failed: Bad search filter: 
\28\28cn\3dj_doe\29\28|\28memberOf\3dcn\3drole_active_emp\2cou\3dportal_role\2cou\3dGroups\2cdc\3dconcordia\2cdc\3dca\29\28memberOf\3dcn\3drole_faculty\2cou\3dportal_role\2cou\3dGroups\2cdc\3dconcordia\2cdc\3dca\29\29\29
rlm_ldap: search failed
rlm_ldap: ldap_release_conn: Release Id: 0
[ldap_host1] returns fail
...

Notice the expand: %{control:CU-LDAP-Filter} line once it's in rlm_ldap.

I suspect that this is happening in the update block, but I can't be
sure of that (or how to avoid it).  I've tried to read all documentation
that refers to update, but haven't yet found any enlightenment.

My update block corresponding to the above is (in sites-enabled/default):

switch %{NAS-IP-Address} {
case 192.168.198.20 {
# test
update control {
   CU-LDAP-Filter = 
((cn=%{%{Stripped-User-Name}:-%{User-Name}})(|(memberOf=cn=role_active_emp,ou=portal_role,ou=Groups,dc=concordia,dc=ca)(memberOf=cn=role_faculty,ou=portal_role,ou=Groups,dc=concordia,dc=ca)))
}
}
...
}

The CU-LDAP-Filter variable is then referenced in the instance(s) of the
ldap module configuration:

ldap ldap_host1 {
...
filter = %{control:CU-LDAP-Filter}
...
}

Hrmmm ...  I see from further reading (man unlang again!) that there is
a 253 character limit on the assignment of string values.  The above
sample is below that limit but the filter values I'm intending to
ultimately use will be well beyond that, so this seems like it perhaps
isn't the best way to get what I'm after.

I'll see if there's some way I could simplify the variable portion of my
LDAP search filter, but I'm bothered by the escaping of punctuation
characters.  Is there a way to un-escape those when the variable is
referred to later?

--
--
Sylvain Robitaille  [EMAIL PROTECTED]

Systems and Network analyst   Concordia University
Instructional  Information TechnologyMontreal, Quebec, Canada
--
-
List info/subscribe/unsubscribe? See 

Re: RADIUS with LDAP: changing LDAP filter based on RADIUS request

2008-06-09 Thread Ivan Kalik
man unlang - attribute lists.

***
The list: prefix is optional, and if omitted, is assumed to refer
to the request list.
 ***

Ivan Kalik
Kalik Informatika ISP


Dana 9/6/2008, Sylvain Robitaille [EMAIL PROTECTED] piše:


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  3000string

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,