r5127: Fix Bug 2289 -- thanks to jason@ncac.gwu.edu
[sfrench/samba-autobuild/.git] / source / lib / system_smbd.c
index 55c2338ebd630ef2713d374da268542f542e6e3b..c83eecf17330eb767dae3bcc88811f09a2249f9c 100644 (file)
@@ -53,7 +53,7 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
                return -1;
        }
        
-       gids_saved = (gid_t *)malloc(sizeof(gid_t) * (ngrp_saved+1));
+       gids_saved = SMB_MALLOC_ARRAY(gid_t, ngrp_saved+1);
        if (!gids_saved) {
                errno = ENOMEM;
                return -1;
@@ -109,15 +109,14 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
 }
 #endif
 
-int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
+static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
 {
-       char *p;
        int retval;
 
        DEBUG(10,("sys_getgrouplist: user [%s]\n", user));
        
        /* see if we should disable winbindd lookups for local users */
-       if ( (p = strchr(user, *lp_winbind_separator())) == NULL ) {
+       if (strchr(user, *lp_winbind_separator()) == NULL) {
                if ( !winbind_off() )
                        DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n",
                                WINBINDD_DONT_ENV));
@@ -139,3 +138,91 @@ int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
        
        return retval;
 }
+
+BOOL getgroups_user(const char *user, gid_t primary_gid,
+                   gid_t **ret_groups, int *ngroups)
+{
+       int ngrp, max_grp;
+       gid_t *temp_groups;
+       gid_t *groups;
+       int i;
+
+       max_grp = groups_max();
+       temp_groups = SMB_MALLOC_ARRAY(gid_t, max_grp);
+       if (! temp_groups) {
+               return False;
+       }
+
+       if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
+               
+               gid_t *groups_tmp;
+               
+               groups_tmp = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp);
+               
+               if (!groups_tmp) {
+                       SAFE_FREE(temp_groups);
+                       return False;
+               }
+               temp_groups = groups_tmp;
+               
+               if (sys_getgrouplist(user, primary_gid,
+                                    temp_groups, &max_grp) == -1) {
+                       DEBUG(0, ("get_user_groups: failed to get the unix "
+                                 "group list\n"));
+                       SAFE_FREE(temp_groups);
+                       return False;
+               }
+       }
+       
+       ngrp = 0;
+       groups = NULL;
+
+       /* Add in primary group first */
+       add_gid_to_array_unique(primary_gid, &groups, &ngrp);
+
+       for (i=0; i<max_grp; i++)
+               add_gid_to_array_unique(temp_groups[i], &groups, &ngrp);
+
+       *ngroups = ngrp;
+       *ret_groups = groups;
+       SAFE_FREE(temp_groups);
+       return True;
+}
+
+NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
+                                           const char *username,
+                                           gid_t primary_gid,
+                                           DOM_SID **sids,
+                                           gid_t **gids,
+                                           int *num_groups)
+{
+       int i;
+
+       if (!getgroups_user(username, primary_gid, gids, num_groups)) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (*num_groups == 0) {
+               smb_panic("primary group missing");
+       }
+
+       *sids = SMB_MALLOC_ARRAY(DOM_SID, *num_groups);
+
+       if (*sids == NULL) {
+               SAFE_FREE(gids);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<*num_groups; i++) {
+               if (!NT_STATUS_IS_OK(gid_to_sid(&(*sids)[i], (*gids)[i]))) {
+                       DEBUG(1, ("get_user_groups: failed to convert "
+                                 "gid %ld to a sid!\n", 
+                                 (long int)(*gids)[i+1]));
+                       SAFE_FREE(*sids);
+                       SAFE_FREE(*gids);
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+       }
+
+       return NT_STATUS_OK;
+}