No subject

Saurabh Lahoti saurabh.astronomy at gmail.com
Sat May 26 12:16:15 CEST 2018


Dear Alan,

Below is the configuration for wifi virtual server: specific to post-auth
section

post-auth {
    if( Airespace-Wlan-Id == 2 ) {
      if( "%{control:LDAP-UserDN}" =~ /ou=guest,ou=wifi,o=mydomain.com$/i )
{
        noop
      }
      elsif( LDAP_Group  == "cn=WiFiGuestPartners,ou=RADIUS
Groups,ou=Groups,ou=staff,o=mydomain.com") {
        noop
      }
    else {
        reject
    }
 }

LDAP module config:
# -*- text -*-
#
#  $Id$

#
#  Lightweight Directory Access Protocol (LDAP)
#
ldap ldapwifi {
        #  Note that this needs to match the name(s) in the LDAP server
        #  certificate, if you're using ldaps.  See OpenLDAP documentation
        #  for the behavioral semantics of specifying more than one host.
        #
        #  Depending on the libldap in use, server may be an LDAP URI.
        #  In the case of OpenLDAP this allows additional the following
        #  additional schemes:
        #  - ldaps:// (LDAP over SSL)
        #  - ldapi:// (LDAP over Unix socket)
        #  - ldapc:// (Connectionless LDAP)
        server = 'ldapcorp.ux.mydomain.com'
#       server = 'ldap.rrdns.example.org'
#       server = 'ldap.rrdns.example.org'

        #  Port to connect on, defaults to 389, will be ignored for LDAP
URIs.
        port = 389

        #  Administrator account for searching and possibly modifying.
        #  If using SASL + KRB5 these should be commented out.
        identity = 'uid=wifiadmin,ou=production,ou=system,o=mydomain.com'
        password = xxxxxxx

        #  Unless overridden in another section, the dn from which all
        #  searches will start from.
        base_dn = 'o=mydomain.com'

        #
        #  SASL parameters to use for admin binds
        #
        #  When we're prompted by the SASL library, these control
        #  the responses given, as well as the identity and password
        #  directives above.
        #
        #  If any directive is commented out, a NULL response will be
        #  provided to cyrus-sasl.
        #
        #  Unfortunately the only way to control Keberos here is through
        #  environmental variables, as cyrus-sasl provides no API to
        #  set the krb5 config directly.
        #
        #  Full documentation for MIT krb5 can be found here:
        #
        #
http://web.mit.edu/kerberos/krb5-devel/doc/admin/env_variables.html
        #
        #  At a minimum you probably want to set KRB5_CLIENT_KTNAME.
        #
#       sasl {
                # SASL mechanism
#               mech = 'PLAIN'

                # SASL authorisation identity to proxy.
#               proxy = 'autz_id'

                # SASL realm. Used for kerberos.
#               realm = 'example.org'
#       }

        #
        #  Generic valuepair attribute
        #

        #  If set, this will attribute will be retrieved in addition to any
        #  mapped attributes.
        #
        #  Values should be in the format:
        #       <radius attr> <op> <value>
        #
        #  Where:
        #       <radius attr>:  Is the attribute you wish to create
        #                       with any valid list and request qualifiers.
        #       <op>:           Is any assignment operator (=, :=, +=, -=).
        #       <value>:        Is the value to parse into the new
valuepair.
        #                       If the value is wrapped in double quotes it
        #                       will be xlat expanded.
#       valuepair_attribute = 'radiusAttribute'

        #
        #  Mapping of LDAP directory attributes to RADIUS dictionary
attributes.
        #

        #  WARNING: Although this format is almost identical to the unlang
        #  update section format, it does *NOT* mean that you can use other
        #  unlang constructs in module configuration files.
        #
        #  Configuration items are in the format:
        #       <radius attr> <op> <ldap attr>
        #
        #  Where:
        #       <radius attr>:  Is the destination RADIUS attribute
        #                       with any valid list and request qualifiers.
        #       <op>:           Is any assignment attribute (=, :=, +=, -=).
        #       <ldap attr>:    Is the attribute associated with user or
        #                       profile objects in the LDAP directory.
        #                       If the attribute name is wrapped in double
        #                       quotes it will be xlat expanded.
        #
        #  Request and list qualifiers may also be placed after the 'update'
        #  section name to set defaults destination requests/lists
        #  for unqualified RADIUS attributes.
        #
        #  Note: LDAP attribute names should be single quoted unless you
want
        #  the name value to be derived from an xlat expansion, or an
        #  attribute ref.
        update {
                control:Password-With-Header    += 'userPassword'
#               control:NT-Password             := 'ntPassword'
#               reply:Reply-Message             := 'radiusReplyMessage'
#               reply:Tunnel-Type               := 'radiusTunnelType'
#               reply:Tunnel-Medium-Type        := 'radiusTunnelMediumType'
#               reply:Tunnel-Private-Group-ID   :=
'radiusTunnelPrivategroupId'

                #  Where only a list is specified as the RADIUS attribute,
                #  the value of the LDAP attribute is parsed as a valuepair
                #  in the same format as the 'valuepair_attribute' (above).
                control:                        += 'radiusControlAttribute'
                request:                        += 'radiusRequestAttribute'
                reply:                          += 'radiusReplyAttribute'
        }

        #  Set to yes if you have eDirectory and want to use the universal
        #  password mechanism.
#       edir = no

        #  Set to yes if you want to bind as the user after retrieving the
        #  Cleartext-Password. This will consume the login grace, and
        #  verify user authorization.
#       edir_autz = no

        #  Note: set_auth_type was removed in v3.x.x
        #  Equivalent functionality can be achieved by adding the following
        #  stanza to the authorize {} section of your virtual server.
        #
        #    ldap
        #    if ((ok || updated) && User-Password) {
        #        update {
        #            control:Auth-Type := ldap
        #        }
        #    }

        #
        #  User object identification.
        #
        user {
                #  Where to start searching in the tree for users
                base_dn = "${..base_dn}"

                #  Filter for user objects, should be specific enough
                #  to identify a single user object.
                #
                #  For Active Directory, you should use
                #  "samaccountname=" instead of "uid="
                #
                filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"

                #  SASL parameters to use for user binds
                #
                #  When we're prompted by the SASL library, these control
                #  the responses given.
                #
                #  Any of the config items below may be an attribute ref
                #  or and expansion, so different SASL mechs, proxy IDs
                #  and realms may be used for different users.
#               sasl {
                        # SASL mechanism
#                       mech = 'PLAIN'

                        # SASL authorisation identity to proxy.
#                       proxy = &User-Name

                        # SASL realm. Used for kerberos.
#                       realm = 'example.org'
#               }

                #  Search scope, may be 'base', 'one', sub' or 'children'
                scope = 'sub'

                #  Server side result sorting
                #
                #  A list of space delimited attributes to order the result
                #  set by, if the filter matches multiple objects.
                #  Only the first result in the set will be processed.
                #
                #  If the attribute name is prefixed with a hyphen '-' the
                #  sorting order will be reversed for that attribute.
                #
                #  If sort_by is set, and the server does not support
sorting
                #  the search will fail.
#               sort_by = '-uid'

                #  If this is undefined, anyone is authorised.
                #  If it is defined, the contents of this attribute
                #  determine whether or not the user is authorised
#               access_attribute = 'dialupAccess'

                #  Control whether the presence of 'access_attribute'
                #  allows access, or denys access.
                #
                #  If 'yes', and the access_attribute is present, or
                #  'no' and the access_attribute is absent then access
                #  will be allowed.
                #
                #  If 'yes', and the access_attribute is absent, or
                #  'no' and the access_attribute is present, then
                #  access will not be allowed.
                #
                #  If the value of the access_attribute is 'false', it
                #  will negate the result.
                #
                #  e.g.
                #    access_positive = yes
                #    access_attribute = userAccessAllowed
                #
                #  With an LDAP object containing:
                #    userAccessAllowed: false
                #
                #  Will result in the user being locked out.
#               access_positive = yes
        }

        #
        #  User membership checking.
        #
        group {
                #  Where to start searching in the tree for groups
                base_dn = "${..base_dn}"

                #  Filter for group objects, should match all available
                #  group objects a user might be a member of.
                filter =
'(&(objectClass=GroupOfUniqueNames)(uniquemember=%{control:LDAP-UserDN}))'

                # Search scope, may be 'base', 'one', sub' or 'children'
                scope = 'sub'

                #  Attribute that uniquely identifies a group.
                #  Is used when converting group DNs to group
                #  names.
                name_attribute = cn

                #  Filter to find group objects a user is a member of.
                #  That is, group objects with attributes that
                #  identify members (the inverse of membership_attribute).
                membership_filter =
"(|(&(objectClass=group)(member=%{control:Ldap-UserDn})))"

                #  The attribute in user objects which contain the names
                #  or DNs of groups a user is a member of.
                #
                #  Unless a conversion between group name and group DN is
                #  needed, there's no requirement for the group objects
                #  referenced to actually exist.
#               membership_attribute = 'memberOf'

                #  If cacheable_name or cacheable_dn are enabled,
                #  all group information for the user will be
                #  retrieved from the directory and written to LDAP-Group
                #  attributes appropriate for the instance of rlm_ldap.
                #
                #  For group comparisons these attributes will be checked
                #  instead of querying the LDAP directory directly.
                #
                #  This feature is intended to be used with rlm_cache.
                #
                #  If you wish to use this feature, you should enable
                #  the type that matches the format of your check items
                #  i.e. if your groups are specified as DNs then enable
                #  cacheable_dn else enable cacheable_name.
#               cacheable_name = 'no'
#               cacheable_dn = 'no'

                #  Override the normal cache attribute (<inst>-LDAP-Group or
                #  LDAP-Group if using the default instance) and create a
                #  custom attribute.  This can help if multiple module
instances
                #  are used in fail-over.
#               cache_attribute = 'LDAP-Cached-Membership'
        }

        #
        #  User profiles. RADIUS profile objects contain sets of attributes
        #  to insert into the request. These attributes are mapped using
        #  the same mapping scheme applied to user objects (the update
section above).
        #
#       profile {
                #  Filter for RADIUS profile objects
#               filter = '(objectclass=radiusprofile)'

                #  The default profile.  This may be a DN or an attribute
                #  reference.
                #  To get old v2.2.x style behaviour, or to use the
                #  &User-Profile attribute to specify the default profile,
                #  set this to &control:User-Profile.
#               default = 'cn=radprofile,dc=example,dc=org'

                #  The LDAP attribute containing profile DNs to apply
                #  in addition to the default profile above.  These are
                #  retrieved from the user object, at the same time as the
                #  attributes from the update section, are are applied
                #  if authorization is successful.
#               attribute = 'radiusProfileDn'
#       }

        #
        #  Bulk load clients from the directory
        #
#       client {
                #   Where to start searching in the tree for clients
#               base_dn = "${..base_dn}"

                #
                #  Filter to match client objects
                #
#               filter = '(objectClass=radiusClient)'

                # Search scope, may be 'base', 'one', 'sub' or 'children'
#               scope = 'sub'

                #
                #  Sets default values (not obtained from LDAP) for new
client entries
                #
#               template {
#                       login                           = 'test'
#                       password                        = 'test'
#                       proto                           = tcp
#                       require_message_authenticator   = yes

                        # Uncomment to add a home_server with the same
                        # attributes as the client.
#                       coa_server {
#                               response_window = 2.0
#                       }
#               }

                #
                #  Client attribute mappings are in the format:
                #      <client attribute> = <ldap attribute>
                #
                #  The following attributes are required:
                #    * ipaddr | ipv4addr | ipv6addr - Client IP Address.
                #    * secret - RADIUS shared secret.
                #
                #  All other attributes usually supported in a client
                #  definition are also supported here.
                #
                #  Schemas are available in doc/schemas/ldap for openldap
and eDirectory
                #
#               attribute {
#                       ipaddr                          =
'radiusClientIdentifier'
#                       secret                          =
'radiusClientSecret'
#                       shortname                       =
'radiusClientShortname'
#                       nas_type                        = 'radiusClientType'
#                       virtual_server                  =
'radiusClientVirtualServer'
#                       require_message_authenticator   =
'radiusClientRequireMa'
#               }
#       }

        #  Load clients on startup
#       read_clients = no

        #
        #  Modify user object on receiving Accounting-Request
        #

        #  Useful for recording things like the last time the user logged
        #  in, or the Acct-Session-ID for CoA/DM.
        #
        #  LDAP modification items are in the format:
        #       <ldap attr> <op> <value>
        #
        #  Where:
        #       <ldap attr>:    The LDAP attribute to add modify or delete.
        #       <op>:           One of the assignment operators:
        #                       (:=, +=, -=, ++).
        #                       Note: '=' is *not* supported.
        #       <value>:        The value to add modify or delete.
        #
        #  WARNING: If using the ':=' operator with a multi-valued LDAP
        #  attribute, all instances of the attribute will be removed and
        #  replaced with a single attribute.
        accounting {
                reference = "%{tolower:type.%{Acct-Status-Type}}"

                type {
                        start {
                                update {
                                        description := "Online at %S"
                                }
                        }

                        interim-update {
                                update {
                                        description := "Last seen at %S"
                                }
                        }

                        stop {
                                update {
                                        description := "Offline at %S"
                                }
                        }
                }
        }

        #
        #  Post-Auth can modify LDAP objects too
        #
        post-auth {
                update {
                        description := "Authenticated at %S"
                }
        }

        #
        #  LDAP connection-specific options.
        #
        #  These options set timeouts, keep-alives, etc. for the
connections.
        #
        options {
                #  Control under which situations aliases are followed.
                #  May be one of 'never', 'searching', 'finding' or 'always'
                #  default: libldap's default which is usually 'never'.
                #
                #  LDAP_OPT_DEREF is set to this value.
#               dereference = 'always'

                #
                #  The following two configuration items control whether the
                #  server follows references returned by LDAP directory.
                #  They are  mostly for Active Directory compatibility.
                #  If you set these to 'no', then searches will likely
return
                #  'operations error', instead of a useful result.
                #
                chase_referrals = yes
                rebind = yes

                # SASL Security Properties (see SASL_SECPROPS in ldap.conf
man page).
                # Note - uncomment when using GSS-API sasl mechanism along
with TLS
                # encryption against Active-Directory LDAP servers (this
disables
                # sealing and signing at the GSS level as required by AD).
                #sasl_secprops = 'noanonymous,noplain,maxssf=0'

                #  Seconds to wait for LDAP query to finish. default: 20
                res_timeout = 10

                #  Seconds LDAP server has to process the query (server-side
                #  time limit). default: 20
                #
                #  LDAP_OPT_TIMELIMIT is set to this value.
                srv_timelimit = 3

                #  Seconds to wait for response of the server. (network
                #  failures) default: 10
                #
                #  LDAP_OPT_NETWORK_TIMEOUT is set to this value.
                net_timeout = 1

                #  LDAP_OPT_X_KEEPALIVE_IDLE
                idle = 60

                #  LDAP_OPT_X_KEEPALIVE_PROBES
                probes = 3

                #  LDAP_OPT_X_KEEPALIVE_INTERVAL
                interval = 3

                #  ldap_debug: debug flag for LDAP SDK
                #  (see OpenLDAP documentation).  Set this to enable
                #  huge amounts of LDAP debugging on the screen.
                #  You should only use this if you are an LDAP expert.
                #
                #       default: 0x0000 (no debugging messages)
                #       Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS)
                ldap_debug = 0x0028
        }

        #
        #  This subsection configures the tls related items
        #  that control how FreeRADIUS connects to an LDAP
        #  server.  It contains all of the 'tls_*' configuration
        #  entries used in older versions of FreeRADIUS.  Those
        #  configuration entries can still be used, but we recommend
        #  using these.
        #
        tls {
                # Set this to 'yes' to use TLS encrypted connections
                # to the LDAP database by using the StartTLS extended
                # operation.
                #
                # The StartTLS operation is supposed to be
                # used with normal ldap connections instead of
                # using ldaps (port 636) connections
                start_tls = no

#               ca_file = ${certdir}/cacert.pem

#               ca_path = ${certdir}
#               certificate_file = /path/to/radius.crt
#               private_key_file = /path/to/radius.key
#               random_file = /dev/urandom

                #  Certificate Verification requirements.  Can be:
                #    'never' (do not even bother trying)
                #    'allow' (try, but don't fail if the certificate
                #               cannot be verified)
                #    'demand' (fail if the certificate does not verify)
                #    'hard'  (similar to 'demand' but fails if TLS
                #             cannot negotiate)
                #
                #  The default is libldap's default, which varies based
                #  on the contents of ldap.conf.

#               require_cert    = 'demand'
        }

        #  As of version 3.0, the 'pool' section has replaced the
        #  following configuration items:
        #
        #  ldap_connections_number

        #  The connection pool is new for 3.0, and will be used in many
        #  modules, for all kinds of connection-related activity.
        #
        #  When the server is not threaded, the connection pool
        #  limits are ignored, and only one connection is used.
        pool {
                #  Connections to create during module instantiation.
                #  If the server cannot create specified number of
                #  connections during instantiation it will exit.
                #  Set to 0 to allow the server to start without the
                #  directory being available.
                start = ${thread[pool].start_servers}

                #  Minimum number of connections to keep open
                min = ${thread[pool].min_spare_servers}

                #  Maximum number of connections
                #
                #  If these connections are all in use and a new one
                #  is requested, the request will NOT get a connection.
                #
                #  Setting 'max' to LESS than the number of threads means
                #  that some threads may starve, and you will see errors
                #  like 'No connections available and at max connection
limit'
                #
                #  Setting 'max' to MORE than the number of threads means
                #  that there are more connections than necessary.
                max = ${thread[pool].max_servers}

                #  Spare connections to be left idle
                #
                #  NOTE: Idle connections WILL be closed if "idle_timeout"
                #  is set.  This should be less than or equal to "max"
above.
                spare = ${thread[pool].max_spare_servers}

                #  Number of uses before the connection is closed
                #
                #  0 means "infinite"
                uses = 0

                #  The number of seconds to wait after the server tries
                #  to open a connection, and fails.  During this time,
                #  no new connections will be opened.
                retry_delay = 30

                #  The lifetime (in seconds) of the connection
                lifetime = 0

                #  Idle timeout (in seconds).  A connection which is
                #  unused for this length of time will be closed.
                idle_timeout = 60

                #  NOTE: All configuration settings are enforced.  If a
                #  connection is closed because of 'idle_timeout',
                #  'uses', or 'lifetime', then the total number of
                #  connections MAY fall below 'min'.  When that
                #  happens, it will open a new connection.  It will
                #  also log a WARNING message.
                #
                #  The solution is to either lower the 'min' connections,
                #  or increase lifetime/idle_timeout.
        }
}

ERROR received:
(0)     if ( Airespace-Wlan-Id == 2 ) {
(0)     if ( Airespace-Wlan-Id == 2 )  -> TRUE
(0)     if ( Airespace-Wlan-Id == 2 )  {
(0)       if ( "%{control:LDAP-UserDN}" =~ /ou=guest,ou=wifi,o= mydomain.com$/i
) {
(0)       EXPAND %{control:LDAP-UserDN}
(0)          --> uid=u5496622,ou=Techmahindra,ou=Partners,o= mydomain.com
(0)       if ( "%{control:LDAP-UserDN}" =~ /ou=guest,ou=wifi,o= mydomain.com
$/i )  -> FALSE
(0)       elsif ( LDAP_Group == "cn=WiFiGuestPartners,ou=RADIUS
Groups,ou=Groups,ou=staff,o=mydomain.com" ) {
(0)       elsif ( LDAP_Group == "cn=WiFiGuestPartners,ou=RADIUS
Groups,ou=Groups,ou=staff,o=mydomain.com )  -> FALSE
(0)       else {
(0)         [reject] = reject
(0)       } # else = reject
(0)     } # if ( Airespace-Wlan-Id == 2 )  = reject
(0)   } # post-auth = reject
(0) Using Post-Auth-Type Reject

Probably, radius isn't able to glance into the LDAP group & search for uid.
Perhaps, query syntax is wrong or incorrect.

Could you please help with correct syntax..?

----

*Thanks & Kind Regards,*
Saurabh LAHOTI.


More information about the Freeradius-Users mailing list