This adds winbind-generated groups showing up in 'getent group'. It is not
authorVolker Lendecke <vlendec@samba.org>
Tue, 2 Mar 2004 14:49:06 +0000 (14:49 +0000)
committerVolker Lendecke <vlendec@samba.org>
Tue, 2 Mar 2004 14:49:06 +0000 (14:49 +0000)
very efficient though, it only does one group at a time. Needs improving, but
the structures are not particularly easy to set up, so check in the basically
working part for others to review.

I'm close to saying that I would like to remove aliases from general group
mapping. These can not be reflected correctly in /etc/group, winbind could do
a better job here.

And having aliases only on machines with nss_winbind at least for me is not a
too severe limitation.

Comments?

Volker

source/nsswitch/winbindd.h
source/nsswitch/winbindd_acct.c
source/nsswitch/winbindd_group.c

index 7c8e6256e15d51ad5e4603f724e498a12627d5d2..340ea07733743eac4d24462426f76ef436e7e0af 100644 (file)
@@ -48,6 +48,11 @@ struct winbindd_cli_state {
        struct winbindd_response response;        /* Respose to client */
        struct getent_state *getpwent_state;      /* State for getpwent() */
        struct getent_state *getgrent_state;      /* State for getgrent() */
+
+       /* Local groups for getgrent() */
+       char **local_group_names;
+       int num_local_group_names;
+       int local_group_ndx;
 };
 
 /* State between get{pw,gr}ent() calls */
index e8d647614b2b6d5c64cb012ef810114916dd4023..28434496ceb7dcb34719382df979126394d3453b 100644 (file)
@@ -1356,5 +1356,55 @@ enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
        return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
 }
 
+static void add_string_to_array(char *name, char ***names, int *num_names)
+{
+       *names = Realloc(*names, (*num_names + 1) * sizeof(char **));
+
+       if (*names == NULL)
+               return;
+
+       (*names)[*num_names] = name;
+       *num_names += 1;
+}
+
+/**********************************************************************
+ List all group names locally defined
+**********************************************************************/
+
+void wb_list_group_names(char ***names, int *num_names)
+{
+       TDB_LIST_NODE *nodes, *node;
+       
+       if (!winbindd_accountdb_init())
+               return;
 
+       nodes = tdb_search_keys(account_tdb, acct_groupkey_byname("*"));
 
+       node = nodes;
+
+       while (node != NULL) {
+               char *name = (char *)node->node_key.dptr;
+
+               DEBUG(10, ("Found key %s\n", name));
+
+               node = node->next;
+
+               /* Skip WBA_GROUP */
+               name = strchr(name, '/');
+               if (name == NULL)
+                       continue;
+               name += 1;
+
+               /* Skip NAME */
+               name = strchr(name, '/');
+               if (name == NULL)
+                       continue;
+               name += 1;
+
+               DEBUG(10, ("adding %s\n", name));
+
+               add_string_to_array(strdup(name), names, num_names);
+       }
+
+       tdb_search_list_free(nodes);
+}
index 90597d9b3fc8fa9ddc5eb093ac3e5a500c600d2d..d09b4ec6f91e87811b10714dff049b49301d4a2b 100644 (file)
@@ -423,6 +423,15 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
                free_getent_state(state->getgrent_state);
                state->getgrent_state = NULL;
        }
+
+       /* Add our locally defined groups */
+
+       state->local_group_names = NULL;
+       state->num_local_group_names = 0;
+       state->local_group_ndx = 0;
+
+       wb_list_group_names(&state->local_group_names,
+                           &state->num_local_group_names);
        
        /* Create sam pipes for each domain we know about */
        
@@ -471,6 +480,80 @@ enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
        return WINBINDD_OK;
 }
 
+/* Fetch group entries from local faked database */
+
+static BOOL return_local_winbind_groups(struct winbindd_cli_state *state)
+{
+       WINBINDD_GR *grp;
+       char *buffer = NULL;
+       char *name;
+       int gr_mem_list_len = 0;
+       struct winbindd_gr *group_list;
+       struct winbindd_gr *gr;
+
+       if (state->local_group_names == NULL)
+               return False;
+
+       name = state->local_group_names[state->local_group_ndx];
+       grp = wb_getgrnam(name);
+
+       if (grp == NULL) {
+               DEBUG(3, ("Group %s vanished\n", name));
+
+               /* Stop that stuff.. */
+               state->local_group_ndx = state->num_local_group_names;
+
+               return False;
+       }
+
+       gr_mem_list_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem );
+
+       state->response.extra_data = malloc(sizeof(struct winbindd_gr) +
+                                           gr_mem_list_len);
+       state->response.length += sizeof(struct winbindd_gr) + gr_mem_list_len;
+
+       group_list = (struct winbindd_gr *)state->response.extra_data;
+
+       if (group_list == NULL) {
+               DEBUG(0, ("Could not malloc group_list\n"));
+               return False;
+       }
+
+       gr = &group_list[0];
+
+       ZERO_STRUCTP(gr);
+
+       gr->gr_gid = grp->gr_gid;
+       safe_strcpy(gr->gr_name, name, sizeof(gr->gr_name) - 1);
+       safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1);
+       gr->num_gr_mem = grp->num_gr_mem;
+       gr->gr_mem_ofs = 0;
+
+       memcpy(&((char *)state->response.extra_data)
+              [sizeof(struct winbindd_gr)],
+              buffer, gr_mem_list_len);
+
+       SAFE_FREE(buffer);
+       SAFE_FREE(grp->gr_mem);
+
+       state->response.data.num_entries = 1;
+
+       state->local_group_ndx += 1;
+
+       if (state->local_group_ndx >= state->num_local_group_names) {
+               int i;
+
+               for (i=0; i<state->num_local_group_names; i++) {
+                       free(state->local_group_names[i]);
+               }
+               free(state->local_group_names);
+               state->local_group_names = NULL;
+       }
+
+       return True;
+}
+
+
 /* Get the list of domain groups and domain aliases for a domain.  We fill in
    the sam_entries and num_sam_entries fields with domain group information.  
    The dispinfo_ndx field is incremented to the index of the next group to 
@@ -606,6 +689,9 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
        if (!lp_winbind_enum_groups())
                return WINBINDD_ERROR;
 
+       if (return_local_winbind_groups(state))
+               return WINBINDD_OK;
+
        num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries);
 
        if ((state->response.extra_data =