summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/nsswitch/winbindd.h5
-rw-r--r--source3/nsswitch/winbindd_acct.c50
-rw-r--r--source3/nsswitch/winbindd_group.c86
3 files changed, 141 insertions, 0 deletions
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 7c8e6256e1..340ea07733 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -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 */
diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c
index e8d647614b..28434496ce 100644
--- a/source3/nsswitch/winbindd_acct.c
+++ b/source3/nsswitch/winbindd_acct.c
@@ -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);
+}
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 90597d9b3f..d09b4ec6f9 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -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 =