|
|
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 |
|