diff options
-rw-r--r-- | src/man/sss_groupshow.8.xml | 2 | ||||
-rw-r--r-- | src/tools/sss_groupshow.c | 244 |
2 files changed, 225 insertions, 21 deletions
diff --git a/src/man/sss_groupshow.8.xml b/src/man/sss_groupshow.8.xml index 13e2dfcb..cb1046b9 100644 --- a/src/man/sss_groupshow.8.xml +++ b/src/man/sss_groupshow.8.xml @@ -45,6 +45,8 @@ <listitem> <para> Also print indirect group members in a tree-like hierarchy. + Note that this also affects printing parent groups - without + <option>R</option>, only the direct parent will be printed. </para> </listitem> </varlistentry> diff --git a/src/tools/sss_groupshow.c b/src/tools/sss_groupshow.c index 2f848b7d..084da21b 100644 --- a/src/tools/sss_groupshow.c +++ b/src/tools/sss_groupshow.c @@ -276,6 +276,7 @@ struct group_show_state { static void group_show_root_done(struct tevent_req *subreq); static void group_show_recurse_done(struct tevent_req *subreq); +static void group_show_trim_done(struct tevent_req *subreq); struct tevent_req *group_show_recurse_send(TALLOC_CTX *, struct group_show_state *, @@ -285,6 +286,17 @@ struct tevent_req *group_show_recurse_send(TALLOC_CTX *, static int group_show_recurse_recv(TALLOC_CTX *, struct tevent_req *, struct group_info ***); +static struct tevent_req *group_show_trim_memberof_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *name, + const char **memberofs); +static int group_show_trim_memberof_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + const char ***direct); + struct tevent_req *group_show_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct sysdb_ctx *sysdb, @@ -355,30 +367,47 @@ static void group_show_root_done(struct tevent_req *subreq) return; } - if (group_members == NULL) { - tevent_req_done(req); - return; - } - if (state->recursive == false) { - /* if not recursive, just fill in names */ - state->root->group_members = talloc_array(state->root, - struct group_info *, - nmembers+1); - for (i=0; group_members[i]; i++) { - state->root->group_members[i] = talloc_zero(state->root, - struct group_info); - if (!state->root->group_members) { - tevent_req_error(req, ENOMEM); - } - state->root->group_members[i]->name = talloc_strdup(state->root, - group_members[i]); - if (!state->root->group_members[i]->name) { - tevent_req_error(req, ENOMEM); + if (group_members) { + state->root->group_members = talloc_array(state->root, + struct group_info *, + nmembers+1); + for (i=0; group_members[i]; i++) { + state->root->group_members[i] = talloc_zero(state->root, + struct group_info); + if (!state->root->group_members) { + tevent_req_error(req, ENOMEM); + return; + } + state->root->group_members[i]->name = talloc_strdup(state->root, + group_members[i]); + if (!state->root->group_members[i]->name) { + tevent_req_error(req, ENOMEM); + return; + } } + state->root->group_members[nmembers] = NULL; } - state->root->group_members[nmembers] = NULL; + if (state->root->memberofs == NULL) { + tevent_req_done(req); + return; + } + + /* if not recursive, only show the direct parent */ + subreq = group_show_trim_memberof_send(state, state->ev, + state->sysdb, state->handle, + state->domain, state->root->name, + state->root->memberofs); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, group_show_trim_done, req); + return; + } + + if (group_members == NULL) { tevent_req_done(req); return; } @@ -394,6 +423,26 @@ static void group_show_root_done(struct tevent_req *subreq) tevent_req_set_callback(subreq, group_show_recurse_done, req); } +static void group_show_trim_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct group_show_state *state = tevent_req_data(req, + struct group_show_state); + int ret; + + ret = group_show_trim_memberof_recv(state->root, subreq, + &state->root->memberofs); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); + return; +} + static void group_show_recurse_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, @@ -428,6 +477,160 @@ static int group_show_recv(TALLOC_CTX *mem_ctx, return EOK; } +/*=========Nonrecursive search should only show direct parent========== */ +struct group_show_trim_state { + const char *name; + struct ldb_dn *dn; + + const char **all; + int current; + + const char **direct; + int ndirect; + + struct tevent_context *ev; + struct sysdb_ctx *sysdb; + struct sysdb_handle *handle; + struct sss_domain_info *domain; +}; + +static int group_show_trim_memberof_next(struct tevent_req *req); +static void group_show_trim_memberof_done(struct tevent_req *subreq); + +static struct tevent_req *group_show_trim_memberof_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *name, + const char **memberofs) +{ + struct tevent_req *req = NULL; + struct group_show_trim_state *state; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct group_show_trim_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->sysdb = sysdb; + state->handle = handle; + state->domain = domain; + state->name = name; + state->all = memberofs; + + state->dn = sysdb_group_dn(state->sysdb, state, + state->domain->name, + state->name); + if (!state->dn) { + talloc_zfree(req); + return NULL; + } + + ret = group_show_trim_memberof_next(req); + if (ret) { + talloc_zfree(req); + return NULL; + } + + return req; +} + +static int group_show_trim_memberof_next(struct tevent_req *req) +{ + const char *filter; + struct tevent_req *subreq = NULL; + struct group_show_trim_state *state = tevent_req_data(req, + struct group_show_trim_state); + + filter = talloc_asprintf(req, "(&(%s=%s)(%s=%s))", + SYSDB_NAME, state->all[state->current], + SYSDB_MEMBER, ldb_dn_get_linearized(state->dn)); + if (!filter) { + return ENOMEM; + } + + subreq = sysdb_search_groups_send(state, state->ev, state->sysdb, + state->handle, state->domain, + filter, NULL); + if (!subreq) { + return ENOMEM; + } + tevent_req_set_callback(subreq, group_show_trim_memberof_done, req); + + return EOK; +} + +static void group_show_trim_memberof_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct group_show_trim_state *state = tevent_req_data(req, + struct group_show_trim_state); + int ret; + struct ldb_message **msgs; + size_t count = 0; + const char *name; + + ret = sysdb_search_groups_recv(subreq, state, &count, &msgs); + talloc_zfree(subreq); + /* ENOENT is OK, the group is just not a direct parent */ + if (ret != EOK && ret != ENOENT) { + tevent_req_error(req, ret); + return; + } + + if (count > 0) { + name = ldb_msg_find_attr_as_string(msgs[0], + SYSDB_NAME, NULL); + if (!name) { + DEBUG(2, ("Entry %s has no Name Attribute ?!?\n", + ldb_dn_get_linearized(msgs[0]->dn))); + tevent_req_error(req, EFAULT); + return; + } + + state->direct = talloc_realloc(state, state->direct, + const char *, state->ndirect+2); + if (!state->direct) { + tevent_req_error(req, ENOMEM); + } + + state->direct[state->ndirect] = talloc_strdup(state->direct, name); + if (!state->direct[state->ndirect]) { + tevent_req_error(req, ENOMEM); + } + + state->direct[state->ndirect+1] = NULL; + state->ndirect++; + } + + state->current++; + if (state->all[state->current] != NULL) { + ret = group_show_trim_memberof_next(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } + return; + } + + tevent_req_done(req); +} + +static int group_show_trim_memberof_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + const char ***direct) +{ + struct group_show_trim_state *state = tevent_req_data(req, + struct group_show_trim_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + *direct = talloc_move(mem_ctx, &state->direct); + + return EOK; +} + /*==================Recursive search for nested groups================= */ struct group_show_recurse { const char **names; @@ -489,7 +692,6 @@ static int group_show_recurse_search(struct tevent_req *req, /* Skip circular groups */ if (strcmp(recurse_state->names[recurse_state->current], recurse_state->parent->name) == 0) { - DEBUG(0, ("CIRCULAR DEP DETECTED\n")); group_show_recurse_cont(req); return EOK; } |