summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/man/sss_groupshow.8.xml2
-rw-r--r--src/tools/sss_groupshow.c244
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;
}