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

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