Finding group members - fix to winbindd_ads.c

Ken Cross kcross at nssolutions.com
Fri Jan 24 04:01:01 GMT 2003


Samba-folk:

There's a problem in the SAMBA_3_0 finding all members of a group using
LDAP (lookup_groupmem in nsswitch/winbindd_ads.c).

It currently gets all the "member" records for a group, but the primary
group membership for users don't get included in that set.  

The primaryGroupID in user records is the RID of the primary group.
That should be included in enumerating the members of any group.

The patch below fixes this.

Ken Cross
Network Storage Solutions



# cvs diff -pu winbindd_ads.c
Index: winbindd_ads.c
===================================================================
RCS file: /cvsroot/samba/source/nsswitch/winbindd_ads.c,v
retrieving revision 1.43.2.7
diff -p -u -r1.43.2.7 winbindd_ads.c
--- winbindd_ads.c      20 Dec 2002 20:21:27 -0000      1.43.2.7
+++ winbindd_ads.c      24 Jan 2003 03:53:47 -0000
@@ -531,13 +531,17 @@ static NTSTATUS lookup_groupmem(struct w
        ADS_STATUS rc;
        int count;
        void *res=NULL;
+       void *res2=NULL;
        ADS_STRUCT *ads = NULL;
        char *exp;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        char *sidstr;
        const char *attrs[] = {"member", NULL};
+       const char *attrs2[] = {"userPrincipalName", "sAMAccountName",
+                               "objectSid", "sAMAccountType", NULL};
        char **members;
-       int i, num_members;
+       char **primaries;
+       int i, num_members=0, num_primaries=0;
 
        *num_names = 0;
 
@@ -554,33 +558,75 @@ static NTSTATUS lookup_groupmem(struct w
        free(sidstr);
 
        if (!ADS_ERR_OK(rc)) {
-               DEBUG(1,("query_user_list ads_search: %s\n",
ads_errstr(rc)));
+               DEBUG(1,("lookup_groupmem ads_search: %s\n",
ads_errstr(rc)));
                goto done;
        }
 
        count = ads_count_replies(ads, res);
-       if (count == 0) {
-               status = NT_STATUS_OK;
+       if (count > 0) {
+                if(members = ads_pull_strings(ads, mem_ctx, res,
"member")) {
+                        for (i=0;members[i];i++) /* noop */ ;
+                        num_members = i;
+                }
+        }
+    
+       if (res) ads_msgfree(ads, res);
+       res = NULL;
+
+       /*
+        * We must also find all users with primaryGroupID == group_rid
+        */
+       asprintf(&exp, "(&(primaryGroupID=%d)(objectClass=user))",
group_rid);
+       rc = ads_search_retry(ads, &res, exp, attrs2);
+       free(exp);
+
+       if (!ADS_ERR_OK(rc)) {
+               DEBUG(1,("lookup_groupmem ads_search: %s\n",
ads_errstr(rc)));
                goto done;
        }
 
-       members = ads_pull_strings(ads, mem_ctx, res, "member");
-       if (!members) {
-               /* no members? ok ... */
-               status = NT_STATUS_OK;
+       num_primaries = ads_count_replies(ads, res);
+
+       (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * (num_members
+ num_primaries));
+       (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) *
(num_members + num_primaries));
+       (*names) = talloc_zero(mem_ctx, sizeof(char *) * (num_members +
num_primaries));
+
+        /* 
+         * Store users whose primary groups match this group.
+         * We have conveniently retrieved all the information we need.
+         */
+        for (res2 = ads_first_entry(ads, res), i=0; res2; 
+             res2 = ads_next_entry(ads, res2), i++) {
+
+            uint32 atype, rid;
+            DOM_SID sid;
+            char *pName;
+            
+            if (i >= num_primaries ) {
+               DEBUG(0,("lookup_groupmem more entries than
counted??"));
                goto done;
+            }
+            
+            pName = ads_pull_username(ads, mem_ctx, res2);
+
+            if (!pName ||
+                !ads_pull_uint32(ads, res2, "sAMAccountType", &atype)
||
+                !ads_pull_sid(ads, res2, "objectSid", &sid) || 
+                !sid_peek_rid(&sid, &rid)) {
+                       DEBUG(3,("lookup_groupmem failed to retrieve
user data\n"));
+                       continue;
+            }
+            (*names)[*num_names] = pName;
+            (*name_types)[*num_names] = ads_atype_map(atype);
+            (*rid_mem)[*num_names] = rid;
+            (*num_names)++;
        }
 
-       /* now we need to turn a list of members into rids, names and
name types 
-          the problem is that the members are in the form of
distinguised names
-       */
-       for (i=0;members[i];i++) /* noop */ ;
-       num_members = i;
-
-       (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * num_members);
-       (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) *
num_members);
-       (*names) = talloc_zero(mem_ctx, sizeof(char *) * num_members);
-
+       /* 
+         * Now we need to turn a list of members into rids, names and
name types
+         * for users whose supplementary groups match this group.
+         * The problem is that the members are in the form of
distinguised names.
+         */
        for (i=0;i<num_members;i++) {
                uint32 name_type, rid;
                char *name;
@@ -594,9 +640,11 @@ static NTSTATUS lookup_groupmem(struct w
        }       
 
        status = NT_STATUS_OK;
-       DEBUG(3,("ads lookup_groupmem for rid=%d\n", group_rid));
+       DEBUG(3,("ads lookup_groupmem for rid=%d found %d members\n", 
+                 group_rid, (num_members + num_primaries)));
 done:
        if (res) ads_msgfree(ads, res);
+       if (res2) ads_msgfree(ads, res2);
 
        return status;
 }




More information about the samba-technical mailing list