Conditional shell:priv-lvl as login reply on CISCO using client's source net and user's ldap attribute.

Alan DeKok aland at
Fri Jan 12 17:12:31 CET 2018

On Jan 12, 2018, at 10:33 AM, Giuseppe Civitella <gcivitella at> wrote:
> I need to enable some users to login on different groups of CISCO
> devices getting different shell:priv-lvl.
> I'm trying to group the devices by their ip using a dynamic-clients
> template. I'd like to send them to a different virtual server based on
> source network of the auth request.

  That should be possible.  But why use dynamic clients?  Why not just use networks for a static client definition?

> Then I'd like to be able to choose which shell:priv-lvl give them using
> LDAP attributes like "o=groupA-shellPriv15" or "o=groupA-shellPriv7".

  That's a separate step.  I'd test that first, and then the dynamic clients later.

> I'm trying to achieve the first result using a configuration like this one:
> client my-dynclient {
>         ipaddr =
>         dynamic_clients = my-dynclients
>         lifetime = 3600
> }

  Sure... but you should really have that defined to be the entire range of networks needed for dynamic clients.  Not just that one network.

  i.e. if you're manually defining one client for each network, you might as well just use static clients.

> server my-dynclients {
>         authorize {
>                 if
> ("%{ldap:ldap:///BASEDN?objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}")
> {
>                         update control {
>                                 &FreeRADIUS-Client-IP-Address =
> "%{Packet-Src-IP-Address}"
>                                 &FreeRADIUS-Client-Shortname =
> "%{ldap:ldap:///BASEDN?radiusClientShortname,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}"
>                                 &FreeRADIUS-Client-Secret =
> "%{ldap:ldap:///BASEDN?radiusClientSecret,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}"
>                                 &FreeRADIUS-Client-Virtual-Server =
> "%{ldap:ldap:///BASEDN?radiusClientVirtualServer,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}"

  What do those LDAP queries return when you run them manually?  One object, or multiple objects?

> ...
> Fri Jan 12 16:12:57 2018 : ERROR: (0)         Bad attributes list in
> LDAP URL. URL must specify exactly one attribute to retrieve
> even if I get for the first time: "Bad attributes list in LDAP URL. URL
> must specify exactly one attribute to retrieve".
> While retrieving  FreeRADIUS-Client-Shortname, FreeRADIUS-Client-Secret
> and FreeRADIUS-Client-Virtual-Server I got empty values and the same
> error about LDAP URL.

  Then your LDAP queries are wrong.  Fix them so that they return the correct data.

> I'm not sure about the debug message, I read that it is not possible to
> get just the value you need using an LDAP uri and no further filtering:
> am I wrong?

  You can do it.  But you need to have the query return one object... as the error message tells you.

> Previously I did try to decide which privilege level send as a
> radiusReply by scanning the LDAP in a similar way:
> post-auth {
> ...
>         if
> ("%{ldap:ldap://BASEDN?objectClass?one?(&(o=groupA-shellPriv15)(cn=%{User-Name})}")
> {
>                update reply {
>                        #reply:ReplyAttribute     += 'cisco-avpair =
> "shell:priv-lvl=15"'
>                        Reply-Message     += "Bingo!!!"
>                }
>         }
> This worked in a setup without dynclients using the Reply-Message and
> raised an error while experimenting with the ReplyAttribute.

  Again, this is an LDAP query issue.  Use the correct queries, and it will work.

  Alan DeKok.

More information about the Freeradius-Users mailing list