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