nss_ldap does not properly look up group members by distinguished name
RFC2307 / RFC2307bis allows for supplementary group members to be enumerated in LDAP using both the 'memberUid' and 'member' attributes. The 'memberUID' is a multi-valued attribute listing uids (i.e. the UNIX login values), while 'member' is a multi-valued attribute contains the LDAP distinguished names of each member. Prior to #10990, the nss_ldap code naively assumed all values of the member attribute would contain distinguished names (DNs) of the form 'uid=XXX,.....' and would merely strip off the first relatively distinguished name (RDN), and return the attribute value.
For directory servers with users that used a naming attribute other than uid (e.g. active directory almost always uses the commonName / cn attribute to name users, resulting in DNs of the form 'cn=xxxxx,.....'), listing group membership via the 'member' attribute of the group object would not work. #10990 fixed this by performing a lookup on each value of the 'member' attribute and the returning the 'uid' attribute (if present, otherwise the entry was skipped). The lookup was performed by searching all of the 'passwd' (i.e. user) base DNs using the search filter
Unfortunately, many common directory servers (including openldap) do not allow you to search based on the 'distinguishedName' (or the alias 'dn') attribute, preventing group members enumerated with the 'member' attribute from being recognized by the OS (as the search will not return any entries). The generally accepted method of looking up an entry by DN is to perform an ldap search with the base DN being the DN you want and a search scope of 'base' (which should be compatible with all LDAP servers). The
__ns_ldap_dn2uid function should be modified to lookup DNs in this manner.
Updated by Jason King over 2 years ago
- File 0001-12240-nss_ldap-does-not-properly-look-up-group-membe.patch 0001-12240-nss_ldap-does-not-properly-look-up-group-membe.patch added
I have a first attempt at fixing this -- the find_domainname() function does something similar to what we want to do for the dn2uid function, so I've tried to factor it out into a bit of common code for both.
Updated by Jorge Schrauwen over 2 years ago
I applied the patch and build a new SmartOS PI as mentioned IRC, I am now getting segfaults in nscd and getent.
Stack from getent core:
Loading modules: [ libc.so.1 libproc.so.1 libnvpair.so.1 libavl.so.1 libuutil.so.1 ld.so.1 ] > $c libc.so.1`realfree+0x40(80b1738) libc.so.1`cleanfree+0x5b(0) libc.so.1`_malloc_unlocked+0xdf(7) libc.so.1`malloc+0x3e(7) libc.so.1`strdup+0x2e(80b17d8) libsldap.so.1`__ns_ldap_dn2uid+0xac(80b4910, 8047738, 0, 804773c) nss_ldap.so.1`getmembers_DN+0x8e(80477a8, 80477ac, 8088af0) nss_ldap.so.1`_nss_ldap_group2str+0x28c(806b148, 8047bc8) nss_ldap.so.1`_nss_ldap_lookup+0x6a(806b148, 8047bc8, fed6d2f6, 8047a40, 0, fed6c458) nss_ldap.so.1`getbynam+0xc7(806b148, 8047bc8) libc.so.1`nss_search+0x1bf(fef4a514, fee4bd40, 4, 8047bc8) libc.so.1`getgrnam_r+0x89(8047e2d, 8066724, 8066734, 4000) libc.so.1`getgrnam+0x49(8047e2d) dogetgr+0xad(8047d24, 80543bd, 8047d1c, fef4a000, 8047d1c, 8065000) main+0x9c(8047cbc, fef57528, 8047cf8, 80528a7, 3, 8047d1c) _start_crt+0x96(3, 8047d1c, fefcff74, 0, 0, 0) _start+0x1a(3, 8047e20, 8047e27, 8047e2d, 0, 8047e34)
Stack from nscd core
Loading modules: [ libumem.so.1 libc.so.1 libuutil.so.1 libavl.so.1 libnvpair.so.1 ld.so.1 ] > $c libc.so.1`_lwp_kill+0x15(4, 6, 0, 1, feaa2000, fea80dfd) libc.so.1`raise+0x2b(6) libumem.so.1`umem_do_abort+0x53() libumem.so.1`__umem_assert_failed(fea80dfd, fea81077, 80e0178) libumem.so.1`process_free+0x74(80e0178, 1, 0) libumem.so.1`umem_malloc_free+0x1a(80e0178) libsldap.so.1`__ns_ldap_freeEntry+0x64(80d6028) libsldap.so.1`__ns_ldap_freeResult+0x46(8121518) nss_ldap.so.1`_nss_ldap_group2str+0xdf(81214f8, fe11bac8) nss_ldap.so.1`_nss_ldap_lookup+0x6a(81214f8, fe11bac8, feccd2f6, fe11b888, 0, feccc458) nss_ldap.so.1`getbynam+0xc7(81214f8, fe11bac8) nss_search+0xa86(0, 8068aa2, 4, fe11bac8) nss_psearch+0xcc(fe11bca0, 80000) lookup_int+0x791(fe19fcb8, 0) nsc_lookup+0x15(fe19fcb8, 0) lookup+0x10a(fe19fd58, a8) switcher+0x151(deadbeed, fe19fd58, a8, 0, 0) libc.so.1`__door_return+0x4b()
Updated by Jason King over 2 years ago
For testing, I setup an LDAP server and loaded some dummy data including 3 groups, 1 with no secondary members, 1 with a secondary member via the
memberUID (by username) attribute, 1 with a secondary member via the
member (by ldap DN) attribute -- a user name 'test' was added as a secondary member to the latter two groups.
Without the changes the groups with secondary members didn't show up (due to #12236).
With the changes (including the fix for #12236), the secondary groups showed up, and displayed the secondary members correctly (
getent group as well as
id -a test).
In addition, since the find_domainname() was refactored to use a common 'lookup by dn' function as part of this fix, I added an /etc/hosts style entry as part of the LDAP data, and then ran
getent hosts to verify the entry appeared. In addition, I was snooping on the LDAP server, and viewed the search request used -- the filter
(nisdomain=*) is only used by the find_domainname function, and that was observed being used for the request -- so
find_domainname was called and was returning correct results.
Jorge was also able to test the final version sent for review and confirmed it fixed his issues.
Updated by Electric Monk over 2 years ago
- Status changed from New to Closed
- % Done changed from 0 to 100
commit d7ab8532a7a0f65d1c2b7bc3f45072f665860b20 Author: Jason King <email@example.com> Date: 2020-02-15T23:23:54.000Z 12236 getmembers_DN doesn't properly handle errors from __ns_ldap_dn2uid 12240 nss_ldap does not properly look up group members by distinguished name Reviewed by: Jorge Schrauwen <firstname.lastname@example.org> Reviewed by: Gordon Ross <email@example.com> Reviewed by: Andy Fiddaman <firstname.lastname@example.org> Reviewed by: Matt Barden <email@example.com> Approved by: Dan McDonald <firstname.lastname@example.org>