ldap module for user and mac authentication
Hello, So background of environment i am testing: master (freeradius and openldap) server - which auths users and provides other services slave (freeradius and openldap) server - which replicates based off of master and *only* auths macs On the SLAVE, I am able to use the ldap module to auth a mac address On the MASTER, i am also able to auth a mac but by doing something like the links below: http://lists.freeradius.org/pipermail/freeradius-users/2015-April/076948.htm... http://lists.freeradius.org/pipermail/freeradius-users/2018-August/092319.ht... Is there a way on the MASTER to use the ldap module to also auth macs? I like the ability to add several ldap servers in conjunction with the "do_not_respond" control policy. Here is the changes i did on the ldap module to make it work for the SLAVE: ldap { server = 'localhost' server = 'master-server' base_dn = 'dc=myorg,dc=net' user { base_dn = "ou=%{config:local.BRN},ou=macs,${..base_dn}" filter = "(cn=%{%{Stripped-User-Name}:-%{User-Name}})" ... } Hope this makes sense. Any input will is appreciated. Thank you, dave
On Aug 7, 2018, at 11:50 AM, Dave Macias <davama@gmail.com> wrote:
On the SLAVE, I am able to use the ldap module to auth a mac address On the MASTER, i am also able to auth a mac but by doing something like the links below: http://lists.freeradius.org/pipermail/freeradius-users/2015-April/076948.htm... http://lists.freeradius.org/pipermail/freeradius-users/2018-August/092319.ht...
Is there a way on the MASTER to use the ldap module to also auth macs?
You can do any kind of LDAP query in FreeRADIUS. Why not just do the same %{ldap:...} checks there? Alan DeKok.
Thank you for the reply Alan!
You can do any kind of LDAP query in FreeRADIUS. Why not just do the same %{ldap:...} checks there?
Yes, I had thought of something to the effect of (suggestions welcomed) : * if (!"%{ldap:ldap://master1/ou=%{client:shortname},ou=macs,dc=myorg,dc=net?cn?sub?(* *&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") {* * if (!"%{ldap:ldap://master2/ou=%{client:shortname},ou=macs,dc=myorg,dc=net?c* *n?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") {* * reject* * }* * }* * update {* * control:Auth-Type := Accept* * }* But this does not account for the scenario of openldap being dead. The 1st "if" statement will be always be FALSE and never attempt the next "if" statement and therefore 'Accept' We currently use do_not_respond in conjunction with the ldap module so that radius never response if openldap it were down http://lists.freeradius.org/pipermail/freeradius-users/2018-May/091477.html The nice feature of the module is that you can configure multiple ldap servers. If one fails then it will automatically try the next and so forth. *mods-enabled/ldap* *ldap {* *server = host1 # <- this one is dead* *server = host2 # <- this one is alive so use this one in the query* *...* *}* Unless there is a way to query the "live" ldap server which the ldap module found %{ldap:ldap://%{live.ldap.server}/...} , if that makes sense Thanks!
On Aug 7, 2018, at 4:04 PM, Dave Macias <davama@gmail.com> wrote:
Yes, I had thought of something to the effect of (suggestions welcomed) : ... But this does not account for the scenario of openldap being dead.
Unfortunately, the dynamic expansions don't deal well with this kind of problem. We're fixing that in v4, but it's hard to do for v3.
Unless there is a way to query the "live" ldap server which the ldap module found %{ldap:ldap://%{live.ldap.server}/...} , if that makes sense
No, there's no way to do that. The fail-over in this case is handled by libldap. So it's completely out of our control. Alan DeKok.
Understood Thank you for the kind assistance Alan! Best Regards, dave On Wed, Aug 8, 2018 at 10:03 AM Alan DeKok <aland@deployingradius.com> wrote:
On Aug 7, 2018, at 4:04 PM, Dave Macias <davama@gmail.com> wrote:
Yes, I had thought of something to the effect of (suggestions welcomed) : ... But this does not account for the scenario of openldap being dead.
Unfortunately, the dynamic expansions don't deal well with this kind of problem.
We're fixing that in v4, but it's hard to do for v3.
Unless there is a way to query the "live" ldap server which the ldap module found %{ldap:ldap://%{live.ldap.server}/...} , if that makes sense
No, there's no way to do that. The fail-over in this case is handled by libldap. So it's completely out of our control.
Alan DeKok.
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
On 8/8/18 4:03 PM, Alan DeKok wrote:
On Aug 7, 2018, at 4:04 PM, Dave Macias <davama@gmail.com> wrote:
Unless there is a way to query the "live" ldap server which the ldap module found %{ldap:ldap://%{live.ldap.server}/...} , if that makes sense
No, there's no way to do that. The fail-over in this case is handled by libldap. So it's completely out of our control.
Maybe I missed something in the thread. But I understand '"live" LDAP server' that you want to know which LDAP server behind connection pooling, load-balancer or similar was really reached. For this particular case I always I add the service FQDN of a particular (OpenLDAP) instance to be readable via LDAP, e.g. in the rootDSE. So a LDAP client can find out to which particular instance it connected even though it does not control the fail-over. Ciao, Michael.
Maybe I missed something in the thread. But I understand '"live" LDAP server' that you want to know which LDAP server behind connection pooling, load-balancer or similar was really reached.
For this particular case I always I add the service FQDN of a particular (OpenLDAP) instance to be readable via LDAP, e.g. in the rootDSE. So a LDAP client can find out to which particular instance it connected even though it does not control the fail-over.
Thank you Michael for the input! That was a good idea! I've got it to work using the ldap SRV, which has multiple ldap servers but using the `ldapsearch` command MASTER:
sites-enabled/default *authorize {* *....* *ldap {* *fail =1* *}* *if (fail) {* *do_not_respond* *}* *if (&NAS-Port-Type == "Ethernet" && &Calling-Station-Id) {*
*rewrite_calling_station_id* *# this method was always TRUE even if the ldap server was dead* *#if (!"%{ldap:ldap://master1/ou=%{client:shortname},ou=macs,dc=datacom,dc=net?cn?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") {* *if `/usr/bin/ldapsearch -x -H "ldap:///dc=test.my.org.net <http://test.my.org.net>" -b "ou=%{client:shortname},ou=macs,dc=myorg,dc=net" "(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))"` {* *update {* *control:Auth-Type := Accept* *}* *}* *else {* *reject* *}* SLAVE: *(no change)* At least with my setup, if all ldap were dead the 'fail = 1' would never allow to reach 'if NAS' where my ldapsearch is. But if 'fail /= 1', even if only 1 master ldap server is alive, then the ldapsearch would use the 'live' ldap server. (note: my ldap module has configured the IPs of the same ldap masters the SRV record resolves to) (note2: I flip the logic of 'if ldapsearch' vs 'if (!"%{ldap:ldap//...}') I could not find a way to use the '{ldap:ldap:///_ldap_srv_record...}' method, since i needed to do a subsearch. This of course makes three programs work together instead of two. (openldap + freeradius + dns). Would have been nicer to have just 2 dependents. But it is neat! Guess depends on your how you want to set it up. Going to try having the SRV record on the ldap module :D Thank you very much for the help! -dave
Yes, I had thought of something to the effect of (suggestions welcomed) :
* if (!"%{ldap:ldap://master1/ou=%{client:shortname},ou=macs,dc=myorg,dc=net?cn?sub?(* *&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") {* * if (!"%{ldap:ldap://master2/ou=%{client:shortname},ou=macs,dc=myorg,dc=net?c* *n?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") {* * reject* * }* * }* * update {* * control:Auth-Type := Accept* * }*
But this does not account for the scenario of openldap being dead. The 1st "if" statement will be always be FALSE and never attempt the next "if" statement and therefore 'Accept'
I believe i misspoke here... But interesting observations. if i use the below code AND have multiple ldap servers configured in my ldap module, radius '%{ldap:ldap:///...}' will automatically go to the one that is alive; assuming one is at least alive. IF i have just one ldap server configured in my ldap module, (which is dead), then the 'if' will FAIL and reject as it should. *if (!"%{ldap:ldap:///ou=%{client:shortname},ou=macs,dc=datacom,dc=net?cn?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") {* *reject* *}* *else {* *update {* *control:Auth-Type := Accept* *}* *}* Same results as above (ldap module will use the live ldap server, not the dead one) *if (!"%{ldap:ldap://dead-ldap-server/ou=%{client:shortname},ou=macs,dc=datacom,dc=net?cn?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}")* *...* *...* So what did i learn? you dont need to use the SRV record for failover, as long as you have all the ldap servers in your ldap module. I think it makes sense since '%{ldap:...}" is using the ldap module, technically, but i would have thought that "ldap:///" or "ldap://dead-ldap-server/" meant localhost/dead-ldap-server not "live.ldap.the-module-found' Or maybe im just completely off... Hope that makes, sense. (1) if (&NAS-Port-Type == "Ethernet" && &Calling-Station-Id) { (1) if (&NAS-Port-Type == "Ethernet" && &Calling-Station-Id) -> TRUE (1) if (&NAS-Port-Type == "Ethernet" && &Calling-Station-Id) { (1) policy rewrite_calling_station_id { (1) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (1) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) -> TRUE (1) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (1) update request { (1) EXPAND %{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}} (1) --> 00-04-F2-DD-98-C6 (1) &Calling-Station-Id := 00-04-F2-DD-98-C6 (1) } # update request = noop (1) [updated] = updated (1) } # if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) = updated (1) ... skipping else: Preceding "if" was taken (1) } # policy rewrite_calling_station_id = updated (1) if (!"%{ldap:ldap:///ou=%{client:shortname},ou=macs,dc=datacom,dc=net?cn?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") { rlm_ldap (ldap): Reserved connection (0) (1) Performing search in "ou=sub-macs,ou=macs,dc=myorg,dc=net" with filter "(&(objectClass=ieee802Device)(macAddress=00-04-F2-DD-98-C6))", scope "sub" (1) Waiting for search result... rlm_ldap (ldap): Released connection (0) Need 5 more connections to reach 10 spares rlm_ldap (ldap): Opening additional connection (5), 1 of 27 pending slots used rlm_ldap (ldap): Connecting to ldap://localhost:389 ldap://ldap2:389 TLSMC: MozNSS compatibility interception begins. tlsmc_convert: INFO: cannot open the NSS DB, expecting PEM configuration is present. tlsmc_intercept_initialization: INFO: successfully intercepted TLS initialization. Continuing with OpenSSL only. TLSMC: MozNSS compatibility interception ends. rlm_ldap (ldap): Waiting for bind result... rlm_ldap (ldap): Bind successful (1) EXPAND %{ldap:ldap:///ou=%{client:shortname},ou=macs,dc=datacom,dc=net?cn?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))} (1) --> 0004f2dd98c6 (1) if (!"%{ldap:ldap:///ou=%{client:shortname},ou=macs,dc=datacom,dc=net?cn?sub?(&(objectClass=ieee802Device)(macAddress=%{Calling-Station-Id}))}") -> FALSE (1) else { (1) update { (1) control:Auth-Type := Accept (1) } # update = noop (1) } # else = noop (1) } # if (&NAS-Port-Type == "Ethernet" && &Calling-Station-Id) = updated (1) ... skipping else: Preceding "if" was taken (1) [expiration] = noop (1) [logintime] = noop (1) pap: WARNING: Auth-Type already set. Not setting to PAP (1) [pap] = noop (1) } # authorize = updated (1) Found Auth-Type = Accept
On 8/9/18 2:23 PM, Dave Macias wrote:
So what did i learn? you dont need to use the SRV record for failover, as long as you have all the ldap servers in your ldap module.
Yes! In theory the advantage of SRV RRs are that you can theoretically change what's in your pool of LDAP servers and adjust priorities based on locations. Besides that I don't believe anybody fully implemented that I'm not a fan of SRV RRs anyway because the TLS hostname check is not even defined for that. Ciao, Michael.
participants (3)
-
Alan DeKok -
Dave Macias -
Michael Ströder