|
|
ced1f5 |
From f048f210112a2ca6df52f10f9e47afac5996fc09 Mon Sep 17 00:00:00 2001
|
|
|
ced1f5 |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
ced1f5 |
Date: Tue, 3 Oct 2017 14:31:18 +0200
|
|
|
ced1f5 |
Subject: [PATCH 07/21] LDAP: Turn group request into user request for MPG
|
|
|
ced1f5 |
domains if needed
|
|
|
ced1f5 |
MIME-Version: 1.0
|
|
|
ced1f5 |
Content-Type: text/plain; charset=UTF-8
|
|
|
ced1f5 |
Content-Transfer-Encoding: 8bit
|
|
|
ced1f5 |
|
|
|
ced1f5 |
If the primary group GID or the group name is requested before the user
|
|
|
ced1f5 |
is, we need to also search the user space to save the user in the back
|
|
|
ced1f5 |
end which then allows the responder to generate the group from the
|
|
|
ced1f5 |
user entry.
|
|
|
ced1f5 |
|
|
|
ced1f5 |
Related:
|
|
|
ced1f5 |
https://pagure.io/SSSD/sssd/issue/1872
|
|
|
ced1f5 |
|
|
|
ced1f5 |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
ced1f5 |
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
|
|
|
ced1f5 |
(cherry picked from commit 057e8af379aa32f7d9ea48bfff22a3304c59444b)
|
|
|
ced1f5 |
---
|
|
|
ced1f5 |
src/providers/ldap/ldap_id.c | 162 +++++++++++++++++++++++++++++++------------
|
|
|
ced1f5 |
1 file changed, 118 insertions(+), 44 deletions(-)
|
|
|
ced1f5 |
|
|
|
ced1f5 |
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
|
|
|
ced1f5 |
index 93204d35ea3782c9aa5d622a962c295869472631..e89fc6133316f684810afe4c1a0731b8a04f2931 100644
|
|
|
ced1f5 |
--- a/src/providers/ldap/ldap_id.c
|
|
|
ced1f5 |
+++ b/src/providers/ldap/ldap_id.c
|
|
|
ced1f5 |
@@ -694,6 +694,8 @@ struct groups_get_state {
|
|
|
ced1f5 |
static int groups_get_retry(struct tevent_req *req);
|
|
|
ced1f5 |
static void groups_get_connect_done(struct tevent_req *subreq);
|
|
|
ced1f5 |
static void groups_get_posix_check_done(struct tevent_req *subreq);
|
|
|
ced1f5 |
+static void groups_get_mpg_done(struct tevent_req *subreq);
|
|
|
ced1f5 |
+static errno_t groups_get_handle_no_group(struct tevent_req *req);
|
|
|
ced1f5 |
static void groups_get_search(struct tevent_req *req);
|
|
|
ced1f5 |
static void groups_get_done(struct tevent_req *subreq);
|
|
|
ced1f5 |
|
|
|
ced1f5 |
@@ -1051,8 +1053,6 @@ static void groups_get_done(struct tevent_req *subreq)
|
|
|
ced1f5 |
struct tevent_req);
|
|
|
ced1f5 |
struct groups_get_state *state = tevent_req_data(req,
|
|
|
ced1f5 |
struct groups_get_state);
|
|
|
ced1f5 |
- char *endptr;
|
|
|
ced1f5 |
- gid_t gid;
|
|
|
ced1f5 |
int dp_error = DP_ERR_FATAL;
|
|
|
ced1f5 |
int ret;
|
|
|
ced1f5 |
|
|
|
ced1f5 |
@@ -1078,49 +1078,33 @@ static void groups_get_done(struct tevent_req *subreq)
|
|
|
ced1f5 |
return;
|
|
|
ced1f5 |
}
|
|
|
ced1f5 |
|
|
|
ced1f5 |
- if (ret == ENOENT && state->noexist_delete == true) {
|
|
|
ced1f5 |
- switch (state->filter_type) {
|
|
|
ced1f5 |
- case BE_FILTER_ENUM:
|
|
|
ced1f5 |
- tevent_req_error(req, ret);
|
|
|
ced1f5 |
+ if (ret == ENOENT
|
|
|
ced1f5 |
+ && state->domain->mpg == true) {
|
|
|
ced1f5 |
+ /* The requested filter did not find a group. Before giving up, we must
|
|
|
ced1f5 |
+ * also check if the GID can be resolved through a primary group of a
|
|
|
ced1f5 |
+ * user
|
|
|
ced1f5 |
+ */
|
|
|
ced1f5 |
+ subreq = users_get_send(state,
|
|
|
ced1f5 |
+ state->ev,
|
|
|
ced1f5 |
+ state->ctx,
|
|
|
ced1f5 |
+ state->sdom,
|
|
|
ced1f5 |
+ state->conn,
|
|
|
ced1f5 |
+ state->filter_value,
|
|
|
ced1f5 |
+ state->filter_type,
|
|
|
ced1f5 |
+ NULL,
|
|
|
ced1f5 |
+ state->noexist_delete);
|
|
|
ced1f5 |
+ if (subreq == NULL) {
|
|
|
ced1f5 |
+ tevent_req_error(req, ENOMEM);
|
|
|
ced1f5 |
return;
|
|
|
ced1f5 |
- case BE_FILTER_NAME:
|
|
|
ced1f5 |
- ret = sysdb_delete_group(state->domain, state->filter_value, 0);
|
|
|
ced1f5 |
- if (ret != EOK && ret != ENOENT) {
|
|
|
ced1f5 |
- tevent_req_error(req, ret);
|
|
|
ced1f5 |
- return;
|
|
|
ced1f5 |
- }
|
|
|
ced1f5 |
- break;
|
|
|
ced1f5 |
-
|
|
|
ced1f5 |
- case BE_FILTER_IDNUM:
|
|
|
ced1f5 |
- gid = (gid_t) strtouint32(state->filter_value, &endptr, 10);
|
|
|
ced1f5 |
- if (errno || *endptr || (state->filter_value == endptr)) {
|
|
|
ced1f5 |
- tevent_req_error(req, errno ? errno : EINVAL);
|
|
|
ced1f5 |
- return;
|
|
|
ced1f5 |
- }
|
|
|
ced1f5 |
-
|
|
|
ced1f5 |
- ret = sysdb_delete_group(state->domain, NULL, gid);
|
|
|
ced1f5 |
- if (ret != EOK && ret != ENOENT) {
|
|
|
ced1f5 |
- tevent_req_error(req, ret);
|
|
|
ced1f5 |
- return;
|
|
|
ced1f5 |
- }
|
|
|
ced1f5 |
- break;
|
|
|
ced1f5 |
-
|
|
|
ced1f5 |
- case BE_FILTER_SECID:
|
|
|
ced1f5 |
- case BE_FILTER_UUID:
|
|
|
ced1f5 |
- /* Since it is not clear if the SID/UUID belongs to a user or a
|
|
|
ced1f5 |
- * group we have nothing to do here. */
|
|
|
ced1f5 |
- break;
|
|
|
ced1f5 |
-
|
|
|
ced1f5 |
- case BE_FILTER_WILDCARD:
|
|
|
ced1f5 |
- /* We can't know if all groups are up-to-date, especially in
|
|
|
ced1f5 |
- * a large environment. Do not delete any records, let the
|
|
|
ced1f5 |
- * responder fetch the entries they are requested in.
|
|
|
ced1f5 |
- */
|
|
|
ced1f5 |
- break;
|
|
|
ced1f5 |
-
|
|
|
ced1f5 |
-
|
|
|
ced1f5 |
- default:
|
|
|
ced1f5 |
- tevent_req_error(req, EINVAL);
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+ tevent_req_set_callback(subreq, groups_get_mpg_done, req);
|
|
|
ced1f5 |
+ return;
|
|
|
ced1f5 |
+ } else if (ret == ENOENT && state->noexist_delete == true) {
|
|
|
ced1f5 |
+ ret = groups_get_handle_no_group(req);
|
|
|
ced1f5 |
+ if (ret != EOK) {
|
|
|
ced1f5 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
ced1f5 |
+ "Could not delete group [%d]: %s\n", ret, sss_strerror(ret));
|
|
|
ced1f5 |
+ tevent_req_error(req, ret);
|
|
|
ced1f5 |
return;
|
|
|
ced1f5 |
}
|
|
|
ced1f5 |
}
|
|
|
ced1f5 |
@@ -1129,6 +1113,96 @@ static void groups_get_done(struct tevent_req *subreq)
|
|
|
ced1f5 |
tevent_req_done(req);
|
|
|
ced1f5 |
}
|
|
|
ced1f5 |
|
|
|
ced1f5 |
+static void groups_get_mpg_done(struct tevent_req *subreq)
|
|
|
ced1f5 |
+{
|
|
|
ced1f5 |
+ errno_t ret;
|
|
|
ced1f5 |
+ struct tevent_req *req = tevent_req_callback_data(subreq,
|
|
|
ced1f5 |
+ struct tevent_req);
|
|
|
ced1f5 |
+ struct groups_get_state *state = tevent_req_data(req,
|
|
|
ced1f5 |
+ struct groups_get_state);
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
|
|
|
ced1f5 |
+ talloc_zfree(subreq);
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ if (ret != EOK) {
|
|
|
ced1f5 |
+ tevent_req_error(req, ret);
|
|
|
ced1f5 |
+ return;
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ if (state->sdap_ret == ENOENT && state->noexist_delete == true) {
|
|
|
ced1f5 |
+ ret = groups_get_handle_no_group(req);
|
|
|
ced1f5 |
+ if (ret != EOK) {
|
|
|
ced1f5 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
ced1f5 |
+ "Could not delete group [%d]: %s\n", ret, sss_strerror(ret));
|
|
|
ced1f5 |
+ tevent_req_error(req, ret);
|
|
|
ced1f5 |
+ return;
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ /* GID resolved to a user private group, done */
|
|
|
ced1f5 |
+ tevent_req_done(req);
|
|
|
ced1f5 |
+ return;
|
|
|
ced1f5 |
+}
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+static errno_t groups_get_handle_no_group(struct tevent_req *req)
|
|
|
ced1f5 |
+{
|
|
|
ced1f5 |
+ struct groups_get_state *state = tevent_req_data(req,
|
|
|
ced1f5 |
+ struct groups_get_state);
|
|
|
ced1f5 |
+ errno_t ret;
|
|
|
ced1f5 |
+ char *endptr;
|
|
|
ced1f5 |
+ gid_t gid;
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ switch (state->filter_type) {
|
|
|
ced1f5 |
+ case BE_FILTER_ENUM:
|
|
|
ced1f5 |
+ ret = ENOENT;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ case BE_FILTER_NAME:
|
|
|
ced1f5 |
+ ret = sysdb_delete_group(state->domain, state->filter_value, 0);
|
|
|
ced1f5 |
+ if (ret != EOK && ret != ENOENT) {
|
|
|
ced1f5 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
ced1f5 |
+ "Cannot delete group %s [%d]: %s\n",
|
|
|
ced1f5 |
+ state->filter_value, ret, sss_strerror(ret));
|
|
|
ced1f5 |
+ return ret;
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+ ret = EOK;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ case BE_FILTER_IDNUM:
|
|
|
ced1f5 |
+ gid = (gid_t) strtouint32(state->filter_value, &endptr, 10);
|
|
|
ced1f5 |
+ if (errno || *endptr || (state->filter_value == endptr)) {
|
|
|
ced1f5 |
+ ret = errno ? errno : EINVAL;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ ret = sysdb_delete_group(state->domain, NULL, gid);
|
|
|
ced1f5 |
+ if (ret != EOK && ret != ENOENT) {
|
|
|
ced1f5 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
ced1f5 |
+ "Cannot delete group %"SPRIgid" [%d]: %s\n",
|
|
|
ced1f5 |
+ gid, ret, sss_strerror(ret));
|
|
|
ced1f5 |
+ return ret;
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+ ret = EOK;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ case BE_FILTER_SECID:
|
|
|
ced1f5 |
+ case BE_FILTER_UUID:
|
|
|
ced1f5 |
+ /* Since it is not clear if the SID/UUID belongs to a user or a
|
|
|
ced1f5 |
+ * group we have nothing to do here. */
|
|
|
ced1f5 |
+ ret = EOK;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ case BE_FILTER_WILDCARD:
|
|
|
ced1f5 |
+ /* We can't know if all groups are up-to-date, especially in
|
|
|
ced1f5 |
+ * a large environment. Do not delete any records, let the
|
|
|
ced1f5 |
+ * responder fetch the entries they are requested in.
|
|
|
ced1f5 |
+ */
|
|
|
ced1f5 |
+ ret = EOK;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ default:
|
|
|
ced1f5 |
+ ret = EINVAL;
|
|
|
ced1f5 |
+ break;
|
|
|
ced1f5 |
+ }
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
+ return ret;
|
|
|
ced1f5 |
+}
|
|
|
ced1f5 |
+
|
|
|
ced1f5 |
int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
|
|
|
ced1f5 |
{
|
|
|
ced1f5 |
struct groups_get_state *state = tevent_req_data(req,
|
|
|
ced1f5 |
--
|
|
|
ced1f5 |
2.13.5
|
|
|
ced1f5 |
|