I am new to radius, and LDAP and am struggling with group level authentication. I want only users in ldap group netadmin
to be authenticated (assuming correct credentials).
In the /etc/raddb/users
file I have added this line to the top of the file:
DEFAULT LDAP-Group == "cn=netadmin,cn=groups,cn=accounts,dc=redacted,dc=redacted,dc=com", Auth-Type := LDAP
In the /etc/raddb/sites-enabled/default
file, at the bottom of the post-auth
block, I have added:
# I am not sure if I need the full ldap path to the group object so I try both
if (LDAP-Group == "netadmin") {
noop
}
elsif (LDAP-Group == "cn=netadmin,cn=groups,cn=accounts,dc=redacted,dc=redacted,dc=com") {
noop
}
else {
reject
}
In the /etc/mods-enabled/ldap
file, I have modified these lines only within these blocks (nothing else is deleted, no ordering is changed):
ldap {
server = 'dc2.redacted.redacted.com'
server = 'dc1.redacted.redacted.com'
base_dn = 'cn=accounts,dc=redacted,dc=redacted,dc=com'
user {
base_dn = "${..base_dn}"
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
scope = 'sub'
}
group {
base_dn = "${..base_dn}"
filter = '(objectClass=ipausergroup)'
membership_attribute = 'memberOf'
scope = 'sub'
}
}
With this, I run radtest locally using credentials that have worked before I made edits to attempt group authentication. In the radius debug output from the server, there are a few lines that stick out to me:
(0) ldap: Login attempt by "myuser"
(0) ldap: Using user DN from request "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com"
(0) ldap: Waiting for bind result...
(0) ldap: Bind successful
(0) ldap: Bind as user "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com" was successful
rlm_ldap (ldap): Released connection (2)
Need 3 more connections to reach 10 spares
rlm_ldap (ldap): Opening additional connection (7), 1 of 25 pending slots used
rlm_ldap (ldap): Connecting to ldap://dc2.redacted.redacted.com:389 ldap://dc1.redacted.redacted.com:389
rlm_ldap (ldap): Waiting for bind result...
rlm_ldap (ldap): Bind successful
(0) [ldap] = ok
(0) } # Auth-Type LDAP = ok
(0) # Executing section post-auth from file /etc/raddb/sites-enabled/default
(0) post-auth {
(0) update {
(0) No attributes updated
(0) } # update = noop
(0) [exec] = noop
(0) policy remove_reply_message_if_eap {
(0) if (&reply:EAP-Message && &reply:Reply-Message) {
(0) if (&reply:EAP-Message && &reply:Reply-Message) -> FALSE
(0) else {
(0) [noop] = noop
(0) } # else = noop
(0) } # policy remove_reply_message_if_eap = noop
(0) if (LDAP-Group == "netadmin") {
(0) Searching for user in group "netadmin"
rlm_ldap (ldap): Reserved connection (3)
(0) Using user DN from request "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com"
(0) Checking user object's memberOf attributes
(0) Performing unfiltered search in "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com", scope "base"
(0) Waiting for search result...
(0) No group membership attribute(s) found in user object
rlm_ldap (ldap): Released connection (3)
(0) User is not a member of "netadmin"
(0) if (LDAP-Group == "netadmin") -> FALSE
Specifically these lines:
(0) Performing unfiltered search in "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com", scope "base"
(0) Waiting for search result...
(0) No group membership attribute(s) found in user object
After using ldapsearch tool, I verified that I have the memberOf
attribute with the netadmin
group:
ldapsearch -P 3 -x -W -D "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com" -b "uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com" \* +
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: * +
#
# myuser, users, accounts, redacted.redacted.com
dn: uid=myuser,cn=users,cn=accounts,dc=redacted,dc=redacted,dc=com
memberOf: cn=ipausers,cn=groups,cn=accounts,dc=redacted,dc=redacted,dc=com
...
memberOf: cn=netadmin,cn=groups,cn=accounts,dc=redacted,dc=redacted,dc=com
...
uid: myuser
objectClass: ipaobject
objectClass: person
objectClass: top
objectClass: ipasshuser
objectClass: inetorgperson
objectClass: organizationalperson
objectClass: krbticketpolicyaux
objectClass: krbprincipalaux
objectClass: inetuser
objectClass: posixaccount
objectClass: ipaSshGroupOfPubKeys
objectClass: mepOriginEntry
I expected the server would see this after searching my users object, and looking for the memberOf
attribute.
I also investigated further and captured packets with tcpdump
and imported into wireshark to compare radtest
and ldapsearch
. I noticed a few differences between the sessions that stuck out to me:
1) The last bindRequest
that radtest
sends before searchRequest
, uses <ROOT>
. Using ldapsearch
, the last bindRequest
uses uid=myuser,cn=groups,cn=accounts,dc=redacted,dc=redacted,dc=com
. BUT I the radius
debug log says that it binds as the authenticated user, so I'm confused here.
2) When ldapsearch
sends the searchRequest
for attribute memberOf
using my users DN
, it uses a scope of wholeSubtree
. When radtest
sends the same request, it uses a scope of base
. This is confusing as I set scope = 'sub'
for both user
and group
blocks in my mods-available/ldap
config.
So what am I missing that is preventing freeradius from seeing the memberOf
attribute data to verify that my user is a part of a group?
Alright I was closer than I thought. After discovering through packet capture that there was some weird binding behaviour, I looked at the debug log more closely. I realized that the binding with my username was being released:
rlm_ldap (ldap): Released connection (2)
Also, the bind that happens for group membership checking does not use my user object DN (I believe this is an anonymous bind):
rlm_ldap (ldap): Opening additional connection (7), 1 of 25 pending slots used
rlm_ldap (ldap): Connecting to ldap://<redacted>:389 ldap://<redacted>:389
rlm_ldap (ldap): Waiting for bind result...
rlm_ldap (ldap): Bind successful
This helped me fine tune my googling and I came across some form discussion.
I asked my system admin if we had any generic accounts for this purpose and we did.
So I included at the top of the ldap block of /etc/mods-enabled/ldap
:
identity = "cn=special_ro_account,....rest_of_dn..."
password = "xxxxxxxx"
And sure enough, the bind was no longer anonymous when searching for group membership and I was successfully authenticated.