Blame SOURCES/0161-RESP-Provide-a-reusable-request-to-fully-resolve-inc.patch

ecf709
From be1f9a082eb28b3346135cbe399f7f909c8a50ce Mon Sep 17 00:00:00 2001
ecf709
From: Jakub Hrozek <jhrozek@redhat.com>
ecf709
Date: Wed, 24 May 2017 17:34:55 +0200
ecf709
Subject: [PATCH 161/166] RESP: Provide a reusable request to fully resolve
ecf709
 incomplete groups
ecf709
MIME-Version: 1.0
ecf709
Content-Type: text/plain; charset=UTF-8
ecf709
Content-Transfer-Encoding: 8bit
ecf709
ecf709
After initgroups, the group objects might not be complete, but just
ecf709
stubs that contain the SID and the GID. If the caller needs to know the
ecf709
group names as well, this request allows them to iterate over the list
ecf709
of the groups and resolve them one-by-one.
ecf709
ecf709
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
ecf709
---
ecf709
 src/responder/common/responder.h       |  14 +++
ecf709
 src/responder/common/responder_utils.c | 206 +++++++++++++++++++++++++++++++++
ecf709
 2 files changed, 220 insertions(+)
ecf709
ecf709
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
ecf709
index dfe1ec455e355de263c3550306e53fea3ada85df..c09ecd4931c9e197fbdfb7835eb72f49cc6f6d3f 100644
ecf709
--- a/src/responder/common/responder.h
ecf709
+++ b/src/responder/common/responder.h
ecf709
@@ -414,4 +414,18 @@ int sized_domain_name(TALLOC_CTX *mem_ctx,
ecf709
                       const char *member_name,
ecf709
                       struct sized_string **_name);
ecf709
 
ecf709
+/* Given a ldb_result structure that contains a result of sysdb_initgroups
ecf709
+ * where some groups might be just 'stubs' that don't have a name, but only
ecf709
+ * a SID and a GID, resolve those incomplete groups into full group objects
ecf709
+ */
ecf709
+struct tevent_req *resp_resolve_group_names_send(TALLOC_CTX *mem_ctx,
ecf709
+                                                 struct tevent_context *ev,
ecf709
+                                                 struct resp_ctx *rctx,
ecf709
+                                                 struct sss_domain_info *dom,
ecf709
+                                                 struct ldb_result *initgr_res);
ecf709
+
ecf709
+int resp_resolve_group_names_recv(TALLOC_CTX *mem_ctx,
ecf709
+                                  struct tevent_req *req,
ecf709
+                                  struct ldb_result **_initgr_named_res);
ecf709
+
ecf709
 #endif /* __SSS_RESPONDER_H__ */
ecf709
diff --git a/src/responder/common/responder_utils.c b/src/responder/common/responder_utils.c
ecf709
index b02212dfd87c2b7c2ca6108d46f939447f0eaa25..7f5c0573087e9c6c885ae158d0677994fd538e2a 100644
ecf709
--- a/src/responder/common/responder_utils.c
ecf709
+++ b/src/responder/common/responder_utils.c
ecf709
@@ -23,6 +23,7 @@
ecf709
 #include <talloc.h>
ecf709
 
ecf709
 #include "responder/common/responder.h"
ecf709
+#include "responder/common/cache_req/cache_req.h"
ecf709
 #include "util/util.h"
ecf709
 
ecf709
 static inline bool
ecf709
@@ -193,3 +194,208 @@ char *sss_resp_create_fqname(TALLOC_CTX *mem_ctx,
ecf709
     talloc_free(tmp_ctx);
ecf709
     return name;
ecf709
 }
ecf709
+
ecf709
+struct resp_resolve_group_names_state {
ecf709
+    struct tevent_context *ev;
ecf709
+    struct resp_ctx *rctx;
ecf709
+    struct sss_domain_info *dom;
ecf709
+    struct ldb_result *initgr_res;
ecf709
+
ecf709
+    bool needs_refresh;
ecf709
+    unsigned int group_iter;
ecf709
+
ecf709
+    struct ldb_result *initgr_named_res;
ecf709
+};
ecf709
+
ecf709
+static void resp_resolve_group_done(struct tevent_req *subreq);
ecf709
+static errno_t resp_resolve_group_next(struct tevent_req *req);
ecf709
+static errno_t resp_resolve_group_reread_names(struct resp_resolve_group_names_state *state);
ecf709
+
ecf709
+struct tevent_req *resp_resolve_group_names_send(TALLOC_CTX *mem_ctx,
ecf709
+                                                 struct tevent_context *ev,
ecf709
+                                                 struct resp_ctx *rctx,
ecf709
+                                                 struct sss_domain_info *dom,
ecf709
+                                                 struct ldb_result *initgr_res)
ecf709
+{
ecf709
+    struct resp_resolve_group_names_state *state;
ecf709
+    struct tevent_req *req;
ecf709
+    errno_t ret;
ecf709
+
ecf709
+    req = tevent_req_create(mem_ctx, &state, struct resp_resolve_group_names_state);
ecf709
+    if (req == NULL) {
ecf709
+        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
ecf709
+        return NULL;
ecf709
+    }
ecf709
+    state->ev = ev;
ecf709
+    state->rctx = rctx;
ecf709
+    state->dom = dom;
ecf709
+    state->initgr_res = initgr_res;
ecf709
+
ecf709
+    ret = resp_resolve_group_next(req);
ecf709
+    if (ret == EOK) {
ecf709
+        goto immediate;
ecf709
+    } else if (ret != EAGAIN) {
ecf709
+        goto immediate;
ecf709
+    }
ecf709
+
ecf709
+    return req;
ecf709
+
ecf709
+immediate:
ecf709
+    if (ret == EOK) {
ecf709
+        tevent_req_done(req);
ecf709
+    } else {
ecf709
+        tevent_req_error(req, ret);
ecf709
+    }
ecf709
+    tevent_req_post(req, ev);
ecf709
+    return req;
ecf709
+}
ecf709
+
ecf709
+static bool
ecf709
+resp_resolve_group_needs_refresh(struct resp_resolve_group_names_state *state)
ecf709
+{
ecf709
+    /* Refresh groups that have a non-zero GID,
ecf709
+     * but are marked as non-POSIX
ecf709
+     */
ecf709
+    bool is_posix;
ecf709
+    uint64_t gid;
ecf709
+    struct ldb_message *group_msg;
ecf709
+
ecf709
+    group_msg = state->initgr_res->msgs[state->group_iter];
ecf709
+
ecf709
+    is_posix = ldb_msg_find_attr_as_bool(group_msg, SYSDB_POSIX, false);
ecf709
+    gid = ldb_msg_find_attr_as_uint64(group_msg, SYSDB_GIDNUM, 0);
ecf709
+
ecf709
+    if (is_posix == false && gid != 0) {
ecf709
+        return true;
ecf709
+    }
ecf709
+
ecf709
+    return false;
ecf709
+}
ecf709
+
ecf709
+static errno_t resp_resolve_group_next(struct tevent_req *req)
ecf709
+{
ecf709
+    struct cache_req_data *data;
ecf709
+    uint64_t gid;
ecf709
+    struct tevent_req *subreq;
ecf709
+    struct resp_resolve_group_names_state *state;
ecf709
+
ecf709
+    state = tevent_req_data(req, struct resp_resolve_group_names_state);
ecf709
+
ecf709
+    while (state->group_iter < state->initgr_res->count
ecf709
+           && !resp_resolve_group_needs_refresh(state)) {
ecf709
+        state->group_iter++;
ecf709
+    }
ecf709
+
ecf709
+    if (state->group_iter >= state->initgr_res->count) {
ecf709
+        /* All groups were refreshed */
ecf709
+        return EOK;
ecf709
+    }
ecf709
+
ecf709
+    /* Fire a request */
ecf709
+    gid = ldb_msg_find_attr_as_uint64(state->initgr_res->msgs[state->group_iter],
ecf709
+                                      SYSDB_GIDNUM, 0);
ecf709
+    if (gid == 0) {
ecf709
+        return EINVAL;
ecf709
+    }
ecf709
+
ecf709
+    data = cache_req_data_id_attrs(state, CACHE_REQ_GROUP_BY_ID, gid, NULL);
ecf709
+    if (data == NULL) {
ecf709
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set cache request data!\n");
ecf709
+        return ENOMEM;
ecf709
+    }
ecf709
+
ecf709
+    subreq = cache_req_send(state,
ecf709
+                            state->ev,
ecf709
+                            state->rctx,
ecf709
+                            state->rctx->ncache,
ecf709
+                            0,
ecf709
+                            CACHE_REQ_ANY_DOM,
ecf709
+                            NULL,
ecf709
+                            data);
ecf709
+    if (subreq == NULL) {
ecf709
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send cache request!\n");
ecf709
+        return ENOMEM;
ecf709
+    }
ecf709
+
ecf709
+    tevent_req_set_callback(subreq, resp_resolve_group_done, req);
ecf709
+    return EAGAIN;
ecf709
+}
ecf709
+
ecf709
+static void resp_resolve_group_done(struct tevent_req *subreq)
ecf709
+{
ecf709
+    struct resp_resolve_group_names_state *state;
ecf709
+    struct tevent_req *req;
ecf709
+    errno_t ret;
ecf709
+
ecf709
+    req = tevent_req_callback_data(subreq, struct tevent_req);
ecf709
+    state = tevent_req_data(req, struct resp_resolve_group_names_state);
ecf709
+
ecf709
+    ret = cache_req_single_domain_recv(state, subreq, NULL);
ecf709
+    talloc_zfree(subreq);
ecf709
+    if (ret != EOK) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh group\n");
ecf709
+        /* Try to refresh the others on error */
ecf709
+    }
ecf709
+
ecf709
+    state->group_iter++;
ecf709
+    state->needs_refresh = true;
ecf709
+
ecf709
+    ret = resp_resolve_group_next(req);
ecf709
+    if (ret == EOK) {
ecf709
+        ret = resp_resolve_group_reread_names(state);
ecf709
+        if (ret != EOK) {
ecf709
+            tevent_req_error(req, ret);
ecf709
+            return;
ecf709
+        }
ecf709
+        DEBUG(SSSDBG_TRACE_FUNC, "All groups are refreshed, done\n");
ecf709
+        tevent_req_done(req);
ecf709
+        return;
ecf709
+    } else if (ret != EAGAIN) {
ecf709
+        tevent_req_error(req, ret);
ecf709
+        return;
ecf709
+    }
ecf709
+
ecf709
+    /* Continue refreshing.. */
ecf709
+}
ecf709
+
ecf709
+static errno_t
ecf709
+resp_resolve_group_reread_names(struct resp_resolve_group_names_state *state)
ecf709
+{
ecf709
+    errno_t ret;
ecf709
+    const char *username;
ecf709
+
ecf709
+    /* re-read reply in case any groups were renamed */
ecf709
+    /* msgs[0] is the user entry */
ecf709
+    username = sss_view_ldb_msg_find_attr_as_string(state->dom,
ecf709
+                                                    state->initgr_res->msgs[0],
ecf709
+                                                    SYSDB_NAME,
ecf709
+                                                    NULL);
ecf709
+    if (username == NULL) {
ecf709
+        DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
ecf709
+        return EINVAL;
ecf709
+    }
ecf709
+
ecf709
+    ret = sysdb_initgroups_with_views(state,
ecf709
+                                      state->dom,
ecf709
+                                      username,
ecf709
+                                      &state->initgr_named_res);
ecf709
+    if (ret != EOK) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "Cannot re-read the group names\n");
ecf709
+        return ret;
ecf709
+    }
ecf709
+
ecf709
+    return EOK;
ecf709
+}
ecf709
+
ecf709
+int resp_resolve_group_names_recv(TALLOC_CTX *mem_ctx,
ecf709
+                                  struct tevent_req *req,
ecf709
+                                  struct ldb_result **_initgr_named_res)
ecf709
+{
ecf709
+    struct resp_resolve_group_names_state *state = NULL;
ecf709
+    state = tevent_req_data(req, struct resp_resolve_group_names_state);
ecf709
+
ecf709
+    TEVENT_REQ_RETURN_ON_ERROR(req);
ecf709
+
ecf709
+    *_initgr_named_res = talloc_steal(mem_ctx, state->initgr_named_res);
ecf709
+    return EOK;
ecf709
+}
ecf709
-- 
ecf709
2.9.4
ecf709