Blame SOURCES/0007-LDAP-Turn-group-request-into-user-request-for-MPG-do.patch

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