In samba3, is it intentional that sam_lookup_groupmem use the "GetMembersInGroup"-type RPC call, instead of GetMembersInAlias?
Goldberg, Neil R.
ngoldber at mitre.org
Thu May 8 13:36:41 MDT 2014
I was trying to use local SAM groups in Winbind the way you might use them on a Windows workstation, including several domain groups in it and using that to control access to a resource.
...In this case for use with pam_wheel for su.
pam_wheel uses getgrent to enumerate the group membership, and in the case of a domain group, it returns the correct list of users.
But when you instead choose a local SAM group, whether a local alias or builtin, it returns no members.
I believe the reason for this discrepancy comes from the way that rpc_lookup_groupmem is implemented (called by sam_lookup_groupmem in winbindd_samr.c) versus how it is accomplished by the winbindd_ads implementation.
In the winbindd_ads.c implementation of lookup_groupmem, it issues an LDAP query for the multi-value member object of the security group by objectSID, fetches the SID and type of every resulting DN (using ads_get_sid_from_extended_dn), and then returns this up to the handler for WINBINDD_GETGRENT .
WINBINDD_GETGRENT checks each member of the result set and if it is a group or alias, and recursively fetches the membership for each of these via the appropriate domain dispatch (local SAM/BUILTIN vs. remote DC). This logic is in wb_group_members_done in wb_group_members.c for the group type counting, and the identification/switching based on domain type is in wb_lookupgroupmem_send.
But if WINBINDD_GETGRENT ends up triggering the sam_lookup_groupmem => rpc_lookup_groupmem path to resolve a group that is for the local system SID or a known BUILTIN, then that's where I think the problem occurs.
rpc_lookup_groupmem makes the assumption that if the group RID being passed to it is an alias (i.e. a Local or Builtin Group), which are the only options for member server SAMs (not acting as a PDC), then it should use the dcerpc_samr_GetAliasMembership call to retrieve the list of local RIDs in the alias. I think the thought was that this should be a parallel construction for the case of a domain group where it returns RIDs from dcerpc_samr_QueryGroupMember, and then the common code path at the end translates all RIDs into SIDs.
There's just one problem with that... QueryGroupMember returns a list of local User RIDs in a Group given the handle from OpenGroup.
GetAliasMembership returns the list of _ALIASES_ to which a passed list of SIDs is a member of (unioned together). If you pass it an alias, it can only return an alias it happens to be a member of (if they are nested). It will never return any user RIDs because the code is only looking for objects in the PDB/LDAP SAM that are Aliases in the first place. This means that if WINBIND_GETGRENT calls lookup_groupmem on a local Alias or Builtin, it can only get a list of more local groups to check, and never any users inside them, and all of them will be empty. This is obviously not what was intended.
The actual function that should be used is: dcerpc_samr_GetMembersInAlias, which returns the membership list of SIDs (which could be local or remote) given an Alias. This function isn't called anywhere from winbindd, when it clearly is the parallel for calling lookup_groupmem for AD domain group membership lookups to be used in sam_lookup_groupmem.
This would require re-writing the function slightly to only use the RID->SID promotion when dealing with the special case of local Global Groups for NT4 PDC emulation.
I'm willing to give this a shot unless there is a reason why SAMR call is used over another that I'm not understanding. I'm pretty sure that the backend implementation does what the definitions say on MSDN for the MS-SAMR RPC... I think there's just been a mixup in that capability, and I don't think many people exercise the SAM integration into winbind enough to trip over this problem.
More information about the samba-technical