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

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