diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/nsswitch/winbindd.h | 5 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_acct.c | 50 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 86 |
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 = |