EAP-TLS with LDAP user attribute check

classic Classic list List threaded Threaded
2 messages Options
| Threaded
Open this post in threaded view
|

EAP-TLS with LDAP user attribute check

stray electron
Hello Everyone,

(short)
How can I check an LDAP group membership (or attribute) in an EAP-TLS setup?
Any help would be appreciated. :)

(long)
I try to set up a Freeradius 3.0 where the client auth is done with EAP-TLS but also checks if the client is in the LDAP (and/or check some user attribute in the LDAP). If the client has a valid certificate but is not in the LDAP then he should be rejected.
Since the auth is already done by EAP-TLS certificates no user bind to the LDAP should be needed, besides I don't have the user password anyway. But I have an LDAP account configured for the Radius server so it can access the user data.

So far EAP-TLS works fine, I suppose the 10-times repetition of the authorize part is due to the EAP messages exchanged with the client, or am I wrong?

Problem is though, that the LDAP search is done 10-times too for each client request. I think this would lead to a huge load of our LDAP server.

I tried to put the ldap stanza into other places like post-auth, but then it tries to write to the LDAP, or in authenticate where the user password is required.
For now I have the LDAP configured that way, that it will do all the attribute filtering/checking for the Radius. So if a user is not allowed to access the WLAN the Radius just does not find the user. But it would be also fine if the Radius itself would do the attribute checking somehow, but I do not know how to import and use these attributes.

Is there a way to reduce the LDAP searches/load somehow?


(0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default
(0)   authorize {
rlm_ldap (ldap): Reserved connection (0)
(0) ldap: EXPAND (uid=%{%{Stripped-User-Name}:-%{User-Name}})
(0) ldap:    --> (uid=clientname)
(0) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(0) ldap: Waiting for search result...
(0) ldap: User object found at DN "uid=clientname,ou=user,o=example,c=de"
(0) ldap: Processing user attributes
rlm_ldap (ldap): Released connection (0)
rlm_ldap (ldap): Opening additional connection (5), 1 of 27 pending slots used
rlm_ldap (ldap): Connecting to ldaps://ldap.example.de:636
rlm_ldap (ldap): Waiting for bind result...
rlm_ldap (ldap): Bind successful
(0)     [ldap] = ok
(0) eap: EAP-Identity reply, returning 'ok' so we can short-circuit the rest of authorize
(0)   } # authorize = ok
(0)   authenticate {
(0)   } # authenticate = handled

...[well this repeats several times, so I shortened it a bit]
(1) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(2) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(3) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(4) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(5) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(6) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(7) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(8) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(9) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
...

(10) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default
(10)   authorize {
rlm_ldap (ldap): Reserved connection (4)
(10) ldap: EXPAND (uid=%{%{Stripped-User-Name}:-%{User-Name}})
(10) ldap:    --> (uid=clientname)
(10) ldap: Performing search in "ou=user,o=example,c=de" with filter "(uid=clientname)", scope "sub"
(10) ldap: Waiting for search result...
(10) ldap: User object found at DN "uid=clientname,ou=user,o=example,c=de"
(10) ldap: Processing user attributes
rlm_ldap (ldap): Released connection (4)
rlm_ldap (ldap): Opening additional connection (6), 1 of 26 pending slots used
rlm_ldap (ldap): Connecting to ldaps://ldap.example.de:636
rlm_ldap (ldap): Waiting for bind result...
rlm_ldap (ldap): Bind successful
(10)     [ldap] = ok
(10)   } # authorize = updated
(10)   authenticate {
(10)   } # authenticate = ok
(10) # Executing section post-auth from file /etc/freeradius/3.0/sites-enabled/default
(10)   post-auth {
(10)   } # post-auth = ok

Regards,
Felix

Freeradius3 Configuration:
------------------------------------

server eduroam {
    listen {
        type = auth
        ipaddr = *
        port = 1812
    }
    authorize {
        linelog_recv_request
        split_username_nai
        if (noop || !&Stripped-User-Domain) {
            reject
        }
        if (&Stripped-User-Domain != "${operator_name}") {
            update {
                control:Load-Balance-Key := &Calling-Station-ID
                control:Proxy-To-Realm := 'eduroam_flr'
               
                request:Operator-Name := "1${operator_name}"
            }
            return
        }
        ldap
        if (!ok) {
            reject
        }
        eap {
            ok = return
            updated = return
        }
    }
    pre-proxy {
        attr_filter.pre-proxy
        linelog_send_proxy_request
    }
    post-proxy {
        attr_filter.post-proxy
        linelog_recv_proxy_response
    }
    authenticate {
        eap
    }
    post-auth {
        update reply {
            Tunnel-Type := VLAN
            Tunnel-Medium-Type := IEEE-802
        }
        if (&control:Proxy-To-Realm) {
            update reply {
                Tunnel-Private-Group-ID = ${eduroam_default_guest_vlan}
            }
        }
        else {
            update reply {
                Tunnel-Private-Group-ID = ${eduroam_default_local_vlan}
            }
        }
        if (&session-state:Stripped-User-Name) {
            update reply {
                User-Name := "%{session-state:Stripped-User-Name}@%{Stripped-User-Domain}"
            }
        }
        linelog_send_accept
        Post-Auth-Type REJECT {
            attr_filter.access_reject
            linelog_send_reject
        }
    }
}


  # Loading module "ldap" from file /etc/freeradius/3.0/mods-enabled/ldap
  ldap {
      server = "ldaps://ldap.example.de:636"
      identity = "cn=radius,ou=accounts,ou=admin,o=example,c=de"
      password = <<< secret >>>
   sasl {
   }
   user {
       scope = "sub"
       access_positive = yes
    sasl {
    }
   }
   group {
       filter = "(objectClass=posixGroup)"
       scope = "sub"
       name_attribute = "cn"
       membership_attribute = "memberOf"
       membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
       cacheable_name = no
       cacheable_dn = no
   }
   client {
       filter = "(objectClass=radiusClient)"
       scope = "sub"
       base_dn = "ou=user,o=example,c=de"
   }
   profile {
   }
   options {
       ldap_debug = 0
       chase_referrals = yes
       rebind = yes
       net_timeout = 1
       res_timeout = 10
       srv_timelimit = 3
       idle = 60
       probes = 3
       interval = 3
   }
   tls {
       ca_file = "/etc/ssl/certs/ca-certificates.crt"
       start_tls = no
       require_cert = "demand"
   }
  }


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP-TLS with LDAP user attribute check

Alan DeKok-2
On Jan 7, 2021, at 8:22 PM, stray electron <[hidden email]> wrote:
> How can I check an LDAP group membership (or attribute) in an EAP-TLS setup?

  Check it once, and cache the result.  Or, check it in post-auth.

> I try to set up a Freeradius 3.0 where the client auth is done with EAP-TLS but also checks if the client is in the LDAP (and/or check some user attribute in the LDAP). If the client has a valid certificate but is not in the LDAP then he should be rejected.

  It's simpler to just revoke the certificate.  But whatever.

> Since the auth is already done by EAP-TLS certificates no user bind to the LDAP should be needed, besides I don't have the user password anyway. But I have an LDAP account configured for the Radius server so it can access the user data.
>
> So far EAP-TLS works fine, I suppose the 10-times repetition of the authorize part is due to the EAP messages exchanged with the client, or am I wrong?

  It's because you made it do the LDAP checks in the "authorize" section, i.e. before the user is authenticated.

> Problem is though, that the LDAP search is done 10-times too for each client request. I think this would lead to a huge load of our LDAP server.
>
> I tried to put the ldap stanza into other places like post-auth, but then it tries to write to the LDAP, or in authenticate where the user password is required.

  You can do:

post-auth {
        ...
        ldap.authorize
        ...
}

  And run the "authorize" method of the "ldap" module.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html