Finding group members - fix to winbindd_ads.c

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


Hmm ... the helpful email client wrapped some of the lines.  The patch
is attached.

Ken


-----Original Message-----
From: samba-technical-admin at lists.samba.org
[mailto:samba-technical-admin at lists.samba.org] On Behalf Of Ken Cross
Sent: Thursday, January 23, 2003 11:01 PM
To: samba-technical at samba.org
Subject: Finding group members - fix to winbindd_ads.c


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
-------------- next part --------------
# 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