On Tue, Jul 26, 2016 at 01:56:38PM +0200, Jakub Hrozek wrote:
> On Tue, Jul 26, 2016 at 01:51:56PM +0200, Sumit Bose wrote:
> > On Mon, Jul 25, 2016 at 01:45:13PM +0200, Jakub Hrozek wrote:
> > > On Thu, Jul 21, 2016 at 02:13:40PM +0200, Sumit Bose wrote:
> > > > Hi,
> > > > 
> > > > this is my suggestion to solve https://fedorahosted.org/sssd/ticket/2948
> > > > "Handle overriden name of members in the memberUid attribute".
> > > 
> > > So far I read them to get a grasp of what they do, but didn't do a full
> > > review. See some comments below.
> > > 
> > > > 
> > > > The first two patches are for the IPA provider and make sure that all
> > > > ghost members in a group get resolved because otherwise we cannot
> > > > determine if the name is overridden or not. This adds an overhead to
> > > > group lookups, especially for larger groups but I think it is an
> > > > requirement which cannot be skipped.
> > > 
> > > Right. But I wonder if we could skip it on-demand. Could we maybe check
> > > if any views exist in the IPA domain at all and not resolve the members
> > > if there are no idview data? I would guess that since this is SSSD on
> > > the IPA server, then an additiona LDAP lookup might be cheaper than
> > > resolving a full large group.
> > 
> > Yes, that would be possible. But since this is about AD users I would
> > prefer a different change.
> > 
> > Since AD used RFC2307bis (member attribute with the DN of the member) we
> > already read the user object from the AD GC when resolving the group but 
> > only
> > ask for objectclass and samAccountName to be able to fill the ghost
> > entry. If we would switch to the LDAP port, read the whole entry and
> > save it to the chance there wouldn't be any ghost entries in the first
> > place. But I wanted to avoid regressions in the common SDAP code at this
> > time so I resolved the ghosts in a second step.
> > 
> > But I guess it is worth to open a ticket to add either or both kinds of
> > optimization.
> 
> OK, I hope with the timestamp cache, the performance impact would only
> be during the first lookup.
> 
> Should I open that ticket or would you?

Please open a ticket.

New version of the patches attached.

bye,
Sumit

> _______________________________________________
> sssd-devel mailing list
> sssd-devel@lists.fedorahosted.org
> https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org
From 5c89f2985fd1aaf8d7b8bd4c00a1e5f2e898398c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Tue, 12 Jul 2016 17:09:00 +0200
Subject: [PATCH 1/4] IPA: make ipa_resolve_user_list_{send|recv} public and
 allow AD users

---
 src/providers/ipa/ipa_id.c | 20 ++++++++++++++++----
 src/providers/ipa/ipa_id.h |  8 ++++++++
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
index 
cfc25b9b322d78bbc64de96227a03ed0604d3391..7f0cd5689dbfde390c162eef340e1120247b703c
 100644
--- a/src/providers/ipa/ipa_id.c
+++ b/src/providers/ipa/ipa_id.c
@@ -71,7 +71,7 @@ struct ipa_resolve_user_list_state {
 static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req);
 static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq);
 
-static struct tevent_req *
+struct tevent_req *
 ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
                            struct ipa_id_ctx *ipa_ctx,
                            const char *domain_name,
@@ -132,7 +132,14 @@ static errno_t ipa_resolve_user_list_get_user_step(struct 
tevent_req *req)
 
     DEBUG(SSSDBG_TRACE_ALL, "Trying to resolve user [%s].\n", 
ar->filter_value);
 
-    subreq = ipa_id_get_account_info_send(state, state->ev, state->ipa_ctx, 
ar);
+    if (strcasecmp(state->domain_name,
+                   state->ipa_ctx->sdap_id_ctx->be->domain->name) != 0) {
+        subreq = ipa_subdomain_account_send(state, state->ev, state->ipa_ctx,
+                                            ar);
+    } else {
+        subreq = ipa_id_get_account_info_send(state, state->ev, state->ipa_ctx,
+                                              ar);
+    }
     if (subreq == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
         return ENOMEM;
@@ -151,7 +158,12 @@ static void ipa_resolve_user_list_get_user_done(struct 
tevent_req *subreq)
                                             struct 
ipa_resolve_user_list_state);
     int ret;
 
-    ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
+    if (strcasecmp(state->domain_name,
+                   state->ipa_ctx->sdap_id_ctx->be->domain->name) != 0) {
+        ret = ipa_subdomain_account_recv(subreq, &state->dp_error);
+    } else {
+        ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
+    }
     talloc_zfree(subreq);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
@@ -182,7 +194,7 @@ done:
     return;
 }
 
-static int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error)
+int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error)
 {
     struct ipa_resolve_user_list_state *state = tevent_req_data(req,
                                             struct 
ipa_resolve_user_list_state);
diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index 
410c2086833d811571195e05a7cab0e2c82fa5b9..4b25498821c6cd0d574c4ce78e4ece29f60459f7
 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -135,4 +135,12 @@ struct tevent_req 
*ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx,
                                                    struct ldb_message 
*user_msg);
 
 errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req);
+
+struct tevent_req *
+ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
+                           struct ipa_id_ctx *ipa_ctx,
+                           const char *domain_name,
+                           struct ldb_message_element *users);
+int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error);
+
 #endif
-- 
2.1.0

From a11b11cb55cf52a7f8f44665547bae141da4c939 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Tue, 12 Jul 2016 17:09:40 +0200
Subject: [PATCH 2/4] IPA: expand ghost members of AD groups in server-mode

---
 src/providers/ipa/ipa_subdomains_id.c | 79 ++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/src/providers/ipa/ipa_subdomains_id.c 
b/src/providers/ipa/ipa_subdomains_id.c
index 
0a89ef5a68802fb7d5f9faeb9ef1d9f9cf8d14f2..7c5deab34f257040a128f09b6617458b8b109b4c
 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -1201,6 +1201,67 @@ fail:
     return;
 }
 
+static void ipa_check_ghost_members_done(struct tevent_req *subreq);
+static errno_t ipa_check_ghost_members(struct tevent_req *req)
+{
+    struct ipa_get_ad_acct_state *state = tevent_req_data(req,
+                                                struct ipa_get_ad_acct_state);
+    errno_t ret;
+    struct tevent_req *subreq;
+    struct ldb_message_element *ghosts = NULL;
+
+
+    if (state->obj_msg == NULL) {
+        ret = get_object_from_cache(state, state->obj_dom, state->ar,
+                                    &state->obj_msg);
+        if (ret == ENOENT) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  "Object not found, ending request\n");
+            return EOK;
+        } else if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
+            return ret;
+        }
+    }
+
+    ghosts = ldb_msg_find_element(state->obj_msg, SYSDB_GHOST);
+
+    if (ghosts != NULL) {
+        /* Resolve ghost members */
+        subreq = ipa_resolve_user_list_send(state, state->ev,
+                                            state->ipa_ctx,
+                                            state->obj_dom->name,
+                                            ghosts);
+        if (subreq == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
+            return ENOMEM;
+        }
+        tevent_req_set_callback(subreq, ipa_check_ghost_members_done, req);
+        return EAGAIN;
+    }
+
+    return EOK;
+}
+
+static void ipa_check_ghost_members_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                struct tevent_req);
+    int ret;
+
+    ret = ipa_resolve_user_list_recv(subreq, NULL);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list request failed [%d]\n",
+                                  ret);
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    tevent_req_done(req);
+    return;
+}
+
 static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
 {
     struct ipa_get_ad_acct_state *state = tevent_req_data(req,
@@ -1228,11 +1289,27 @@ static errno_t ipa_get_ad_apply_override_step(struct 
tevent_req *req)
     entry_type = (state->ar->entry_type & BE_REQ_TYPE_MASK);
     if (entry_type != BE_REQ_INITGROUPS
             && entry_type != BE_REQ_USER
-            && entry_type != BE_REQ_BY_SECID) {
+            && entry_type != BE_REQ_BY_SECID
+            && entry_type != BE_REQ_GROUP) {
         tevent_req_done(req);
         return EOK;
     }
 
+    /* expand ghost members, if any, to get group members with overrides
+     * right. */
+    if (entry_type == BE_REQ_GROUP) {
+        ret = ipa_check_ghost_members(req);
+        if (ret == EOK) {
+            tevent_req_done(req);
+            return EOK;
+        } else if (ret == EAGAIN) {
+            return EOK;
+        } else {
+            DEBUG(SSSDBG_OP_FAILURE, "ipa_check_ghost_members failed.\n");
+            return ret;
+        }
+    }
+
     /* Replace ID with name in search filter */
     if ((entry_type == BE_REQ_USER && state->ar->filter_type == 
BE_FILTER_IDNUM)
             || (entry_type == BE_REQ_INITGROUPS
-- 
2.1.0

From 5596a3cb36c9f0d0b8ecbcd68f82bc3d7b040b55 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Wed, 20 Jul 2016 18:42:27 +0200
Subject: [PATCH 3/4] sysdb: add sysdb_get_user_members_recursively()

---
 src/db/sysdb.h     |   5 ++
 src/db/sysdb_ops.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 211 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 
0cc550a4c389b4a1a2b78aff760f4b5cbf94e17f..405f89e2f1ac6fabc06e77c345de8693845f9d92
 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -1257,6 +1257,11 @@ errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
                                   const char ***_dns,
                                   size_t *_n);
 
+errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx,
+                                           struct sss_domain_info *dom,
+                                           struct ldb_dn *group_dn,
+                                           struct ldb_result **members);
+
 errno_t sysdb_handle_original_uuid(const char *orig_name,
                                    struct sysdb_attrs *src_attrs,
                                    const char *src_name,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 
19d6be03ede1bcec3bc7a4ed777e326460d80591..b7c04cb4ab64c2767e211d6ead1463a3a3024e68
 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -4711,6 +4711,212 @@ done:
     return ret;
 }
 
+static
+errno_t sysdb_get_user_members_recursively_int(TALLOC_CTX *mem_ctx,
+                                               struct sss_domain_info *dom,
+                                               struct ldb_dn *group_dn,
+                                               hash_table_t *users,
+                                               hash_table_t *groups)
+{
+    errno_t ret;
+    size_t c;
+    size_t m_count;
+    struct ldb_message **members;
+    const char *oc;
+    hash_key_t key;
+    hash_value_t value;
+    int hret;
+
+    /* Get all elemets pointed to by group members */
+    ret = sysdb_asq_search(mem_ctx, dom, group_dn, NULL, SYSDB_MEMBER,
+                           NULL /* requesting all attributes */,
+                           &m_count, &members);
+    if (ret != EOK) {
+        if (ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_asq_search failed.\n");
+        }
+        goto done;
+    }
+
+    key.type = HASH_KEY_STRING;
+
+    for (c = 0; c < m_count; c++) {
+
+        oc = ldb_msg_find_attr_as_string(members[c], SYSDB_OBJECTCLASS, NULL);
+        if (oc == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "Missing objectclass in object [%s].\n",
+                  ldb_dn_get_linearized(members[c]->dn));
+            ret = EINVAL;
+            goto done;
+        }
+
+        if (strcmp(oc, SYSDB_USER_CLASS) == 0) {
+            key.str = discard_const(ldb_dn_get_linearized(members[c]->dn));
+            if (key.str == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized failed.\n");
+                ret = EFAULT;
+                goto done;
+            }
+
+            value.type = HASH_VALUE_PTR;
+            value.ptr = members[c];
+
+            hret = hash_enter(users, &key, &value);
+            if (hret != HASH_SUCCESS) {
+                DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed.\n");
+                ret = ENOMEM;
+                goto done;
+            }
+
+        } else if (strcmp(oc, SYSDB_GROUP_CLASS) == 0) {
+            key.str = discard_const(ldb_dn_get_linearized(members[c]->dn));
+            if (key.str == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized failed.\n");
+                ret = EFAULT;
+                goto done;
+            }
+
+            hret = hash_lookup(groups, &key, &value);
+            if (hret == HASH_SUCCESS) {
+                /* Already seen this group, skipping */
+                continue;
+            } else if (hret != HASH_ERROR_KEY_NOT_FOUND) {
+                DEBUG(SSSDBG_OP_FAILURE, "hash_lookup failed.\n");
+                ret = EFAULT;
+                goto done;
+            }
+
+            /* group was not found in the hash, adding and processing it */
+
+            value.type = HASH_VALUE_PTR;
+            value.ptr = members[c];
+
+            hret = hash_enter(groups, &key, &value);
+            if (hret != HASH_SUCCESS) {
+                DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed.\n");
+                ret = ENOMEM;
+                goto done;
+            }
+
+            ret = sysdb_get_user_members_recursively_int(mem_ctx, dom,
+                                                         members[c]->dn,
+                                                         users, groups);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                      "sysdb_get_user_members_recursively_int failed.\n");
+                goto done;
+            }
+
+        } else {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Unexpected objectclass [%s] in object [%s].\n", oc,
+                  ldb_dn_get_linearized(members[c]->dn));
+            ret = EINVAL;
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+
+    return ret;
+}
+
+errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx,
+                                           struct sss_domain_info *dom,
+                                           struct ldb_dn *group_dn,
+                                           struct ldb_result **members)
+{
+    TALLOC_CTX *tmp_ctx;
+    hash_table_t *users;
+    hash_table_t *groups;
+    int ret;
+    int hret;
+    size_t c;
+    unsigned long count;
+    struct ldb_result *res;
+    hash_value_t *values;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sss_hash_create(tmp_ctx, 10, &users);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n");
+        goto done;
+    }
+
+    ret = sss_hash_create(tmp_ctx, 10, &groups);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n");
+        goto done;
+    }
+
+    ret = sysdb_get_user_members_recursively_int(tmp_ctx, dom, group_dn, users,
+                                                 groups);
+    if (ret != EOK) {
+        if (ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_get_user_members_recursively_int failed.\n");
+        }
+        goto done;
+    }
+
+    res = talloc_zero(tmp_ctx, struct ldb_result);
+    if (res == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    hret = hash_values(users, &count, &values);
+    if (hret != HASH_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "hash_values failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+    if (count <= UINTMAX_MAX) {
+        res->count = count;
+    } else {
+        DEBUG(SSSDBG_CRIT_FAILURE, "More then [%"PRIuMAX"] results.\n",
+                                   UINTMAX_MAX);
+        ret = EINVAL;
+        goto done;
+    }
+    if (res->count == 0) {
+        ret = EOK;
+        goto done;
+    }
+
+    res->msgs = talloc_array(res, struct ldb_message *, res->count);
+    if (res->msgs == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    for (c = 0; c < res->count; c++) {
+        res->msgs[c] = (struct ldb_message *) talloc_steal(res->msgs,
+                                                           values[c].ptr);
+    }
+
+    ret = EOK;
+
+done:
+    if (ret == EOK) {
+        *members = talloc_steal(mem_ctx, res);
+    } else if (ret == ENOENT) {
+        DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n");
+    } else {
+        DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
+    }
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 errno_t sysdb_handle_original_uuid(const char *orig_name,
                                    struct sysdb_attrs *src_attrs,
                                    const char *src_name,
-- 
2.1.0

From 57ec193fd6a4d5014ef47a720dae74fdf6df2207 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 7 Jul 2016 18:54:02 +0200
Subject: [PATCH 4/4] views: properly override group member names

Resolves https://fedorahosted.org/sssd/ticket/2948
---
 src/db/sysdb.h                  |   3 +-
 src/db/sysdb_search.c           |  99 ++++++++++++++++-------------
 src/db/sysdb_views.c            | 136 ++++++++++++++++++----------------------
 src/responder/nss/nsssrv_cmd.c  |   7 ++-
 src/tests/cmocka/test_nss_srv.c |  26 ++++----
 5 files changed, 138 insertions(+), 133 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 
405f89e2f1ac6fabc06e77c345de8693845f9d92..a27552224bb40bd07c7dee4dfe35bfb7a0b4f2c3
 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -572,7 +572,8 @@ errno_t sysdb_add_overrides_to_object(struct 
sss_domain_info *domain,
                                       const char **req_attrs);
 
 errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-                                         struct ldb_message *obj);
+                                         struct ldb_message *obj,
+                                         bool expect_override_dn);
 
 errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx,
                                   struct sss_domain_info *domain,
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 
e40b36c38e28992e185447497d1bf69cabc09821..cfee5784dbadd692f30d0758e7e5c3c9fb2814cb
 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -771,28 +771,33 @@ int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx,
 
     /* If there are views we have to check if override values must be added to
      * the original object. */
-    if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
-        if (!is_local_view(domain->view_name)) {
-            el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
-            if (el != NULL && el->num_values != 0) {
-                DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost "
-                      "entries which must be resolved before overrides can be "
-                      "applied.\n",
-                      ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
-                ret = ENOENT;
+    if (orig_obj->count == 1) {
+        if (DOM_HAS_VIEWS(domain)) {
+            if (!is_local_view(domain->view_name)) {
+                el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
+                if (el != NULL && el->num_values != 0) {
+                    DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost 
"
+                          "entries which must be resolved before overrides can 
be "
+                          "applied.\n",
+                          ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
+                    ret = ENOENT;
+                    goto done;
+                }
+            }
+
+            ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
+                           override_obj == NULL ? NULL : override_obj 
->msgs[0],
+                           NULL);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object 
failed.\n");
                 goto done;
             }
         }
 
-        ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
-                          override_obj == NULL ? NULL : override_obj ->msgs[0],
-                          NULL);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object 
failed.\n");
-            goto done;
-        }
-
-        ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]);
+        /* Must be called even without views to check to
+         * SYSDB_DEFAULT_OVERRIDE_NAME */
+        ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0],
+                                               DOM_HAS_VIEWS(domain));
         if (ret != EOK) {
             DEBUG(SSSDBG_OP_FAILURE,
                   "sysdb_add_group_member_overrides failed.\n");
@@ -922,28 +927,33 @@ int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx,
 
     /* If there are views we have to check if override values must be added to
      * the original object. */
-    if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
-        if (!is_local_view(domain->view_name)) {
-            el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
-            if (el != NULL && el->num_values != 0) {
-                DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost "
-                      "entries which must be resolved before overrides can be "
-                      "applied.\n",
-                      ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
-                ret = ENOENT;
+    if (orig_obj->count == 1) {
+        if (DOM_HAS_VIEWS(domain)) {
+            if (!is_local_view(domain->view_name)) {
+                el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
+                if (el != NULL && el->num_values != 0) {
+                    DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost 
"
+                          "entries which must be resolved before overrides can 
be "
+                          "applied.\n",
+                          ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
+                    ret = ENOENT;
+                    goto done;
+                }
+            }
+
+            ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
+                              override_obj == NULL ? NULL : override_obj 
->msgs[0],
+                              NULL);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object 
failed.\n");
                 goto done;
             }
         }
 
-        ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
-                          override_obj == NULL ? NULL : override_obj ->msgs[0],
-                          NULL);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object 
failed.\n");
-            goto done;
-        }
-
-        ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]);
+        /* Must be called even without views to check to
+         * SYSDB_DEFAULT_OVERRIDE_NAME */
+        ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0],
+                                               DOM_HAS_VIEWS(domain));
         if (ret != EOK) {
             DEBUG(SSSDBG_OP_FAILURE,
                   "sysdb_add_group_member_overrides failed.\n");
@@ -1157,8 +1167,8 @@ int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    if (DOM_HAS_VIEWS(domain)) {
-        for (c = 0; c < res->count; c++) {
+    for (c = 0; c < res->count; c++) {
+        if (DOM_HAS_VIEWS(domain)) {
             ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
                                                 NULL);
             /* enumeration assumes that the cache is up-to-date, hence we do 
not
@@ -1167,13 +1177,14 @@ int sysdb_enumgrent_filter_with_views(TALLOC_CTX 
*mem_ctx,
                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object 
failed.\n");
                 goto done;
             }
+        }
 
-            ret = sysdb_add_group_member_overrides(domain, res->msgs[c]);
-            if (ret != EOK) {
-                DEBUG(SSSDBG_OP_FAILURE,
-                      "sysdb_add_group_member_overrides failed.\n");
-                goto done;
-            }
+        ret = sysdb_add_group_member_overrides(domain, res->msgs[c],
+                                               DOM_HAS_VIEWS(domain));
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_add_group_member_overrides failed.\n");
+            goto done;
         }
     }
 
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index 
2b89e5ca41f719e1217ef3b9e0fd683656e05d42..79f513d13ba41212a6cd84e1d9e609df6acba29c
 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -1348,14 +1348,13 @@ done:
 }
 
 errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-                                         struct ldb_message *obj)
+                                         struct ldb_message *obj,
+                                         bool expect_override_dn)
 {
     int ret;
     size_t c;
-    struct ldb_message_element *members;
+    struct ldb_result *res_members;
     TALLOC_CTX *tmp_ctx;
-    struct ldb_dn *member_dn;
-    struct ldb_result *member_obj;
     struct ldb_result *override_obj;
     static const char *member_attrs[] = SYSDB_PW_ATTRS;
     const char *override_dn_str;
@@ -1366,12 +1365,6 @@ errno_t sysdb_add_group_member_overrides(struct 
sss_domain_info *domain,
     char *val;
     struct sss_domain_info *orig_dom;
 
-    members = ldb_msg_find_element(obj, SYSDB_MEMBER);
-    if (members == NULL || members->num_values == 0) {
-        DEBUG(SSSDBG_TRACE_ALL, "Group has no members.\n");
-        return EOK;
-    }
-
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
@@ -1379,38 +1372,30 @@ errno_t sysdb_add_group_member_overrides(struct 
sss_domain_info *domain,
         goto done;
     }
 
-    for (c = 0; c < members->num_values; c++) {
-        member_dn = ldb_dn_from_ldb_val(tmp_ctx, domain->sysdb->ldb,
-                                        &members->values[c]);
-        if (member_dn == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_from_ldb_val failed.\n");
-            ret = ENOMEM;
-            goto done;
-        }
+    ret = sysdb_get_user_members_recursively(tmp_ctx, domain, obj->dn,
+                                             &res_members);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "sysdb_get_user_members_recursively failed.\n");
+        goto done;
+    }
 
-        ret = ldb_search(domain->sysdb->ldb, member_dn, &member_obj, member_dn,
-                         LDB_SCOPE_BASE, member_attrs, NULL);
-        if (ret != LDB_SUCCESS) {
-            ret = sysdb_error_to_errno(ret);
-            goto done;
-        }
+    for (c = 0; c < res_members->count; c++) {
 
-        if (member_obj->count != 1) {
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Base search for member object returned [%d] results.\n",
-                  member_obj->count);
-            ret = EINVAL;
-            goto done;
-        }
-
-        if (ldb_msg_find_attr_as_uint64(member_obj->msgs[0],
+        if (ldb_msg_find_attr_as_uint64(res_members->msgs[c],
                                         SYSDB_UIDNUM, 0) == 0) {
             /* Skip non-POSIX-user members i.e. groups and non-POSIX users */
             continue;
         }
 
-        override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0],
-                                                      SYSDB_OVERRIDE_DN, NULL);
+        if (expect_override_dn) {
+            override_dn_str = ldb_msg_find_attr_as_string(res_members->msgs[c],
+                                                          SYSDB_OVERRIDE_DN,
+                                                          NULL);
+        } else {
+            override_dn_str = ldb_dn_get_linearized(res_members->msgs[c]->dn);
+        }
+
         if (override_dn_str == NULL) {
             if (is_local_view(domain->view_name)) {
                 /* LOCAL view doesn't have to have overrideDN specified. */
@@ -1420,12 +1405,12 @@ errno_t sysdb_add_group_member_overrides(struct 
sss_domain_info *domain,
 
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Missing override DN for object [%s].\n",
-                  ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+                  ldb_dn_get_linearized(res_members->msgs[c]->dn));
             ret = ENOENT;
             goto done;
         }
 
-        override_dn = ldb_dn_new(member_obj, domain->sysdb->ldb,
+        override_dn = ldb_dn_new(res_members, domain->sysdb->ldb,
                                  override_dn_str);
         if (override_dn == NULL) {
             DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
@@ -1433,22 +1418,27 @@ errno_t sysdb_add_group_member_overrides(struct 
sss_domain_info *domain,
             goto done;
         }
 
-        orig_name = ldb_msg_find_attr_as_string(member_obj->msgs[0],
+        orig_name = ldb_msg_find_attr_as_string(res_members->msgs[c],
                                                 SYSDB_NAME,
                                                 NULL);
         if (orig_name == NULL) {
             DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n",
-                  ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+                  ldb_dn_get_linearized(res_members->msgs[c]->dn));
             ret = EINVAL;
             goto done;
         }
 
-        memberuid = NULL;
-        if (ldb_dn_compare(member_obj->msgs[0]->dn, override_dn) != 0) {
+        /* start with default view name, if it exists or use NULL */
+        memberuid = ldb_msg_find_attr_as_string(res_members->msgs[c],
+                                                SYSDB_DEFAULT_OVERRIDE_NAME,
+                                                NULL);
+
+        /* If there is an override object, check if the name is overridden */
+        if (ldb_dn_compare(res_members->msgs[c]->dn, override_dn) != 0) {
             DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n",
-                  ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+                  ldb_dn_get_linearized(res_members->msgs[c]->dn));
 
-            ret = ldb_search(domain->sysdb->ldb, member_obj, &override_obj,
+            ret = ldb_search(domain->sysdb->ldb, res_members, &override_obj,
                              override_dn, LDB_SCOPE_BASE, member_attrs, NULL);
             if (ret != LDB_SUCCESS) {
                 ret = sysdb_error_to_errno(ret);
@@ -1458,43 +1448,44 @@ errno_t sysdb_add_group_member_overrides(struct 
sss_domain_info *domain,
             if (override_obj->count != 1) {
                 DEBUG(SSSDBG_CRIT_FAILURE,
                      "Base search for override object returned [%d] 
results.\n",
-                     member_obj->count);
+                    override_obj->count);
                 ret = EINVAL;
                 goto done;
             }
 
             memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0],
                                                     SYSDB_NAME,
-                                                    NULL);
+                                                    memberuid);
+        }
 
-            if (memberuid != NULL) {
-                ret = sss_parse_internal_fqname(tmp_ctx, orig_name,
-                                                NULL, &orig_domain);
-                if (ret != EOK) {
-                    DEBUG(SSSDBG_OP_FAILURE,
-                         "sss_parse_internal_fqname failed to split [%s].\n",
-                         orig_name);
+        /* add domain name if memberuid is a short name */
+        if (memberuid != NULL && strchr(memberuid, '@') == NULL) {
+            ret = sss_parse_internal_fqname(tmp_ctx, orig_name,
+                                            NULL, &orig_domain);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                     "sss_parse_internal_fqname failed to split [%s].\n",
+                     orig_name);
+                goto done;
+            }
+
+            if (orig_domain != NULL) {
+                orig_dom = find_domain_by_name(get_domains_head(domain),
+                                               orig_domain, true);
+                if (orig_dom == NULL) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "Cannot find domain with name [%s].\n",
+                          orig_domain);
+                    ret = ERR_DOMAIN_NOT_FOUND;
                     goto done;
                 }
-
-                if (orig_domain != NULL) {
-                    orig_dom = find_domain_by_name(get_domains_head(domain),
-                                                   orig_domain, true);
-                    if (orig_dom == NULL) {
-                        DEBUG(SSSDBG_CRIT_FAILURE,
-                              "Cannot find domain with name [%s].\n",
-                              orig_domain);
-                        ret = ERR_DOMAIN_NOT_FOUND;
-                        goto done;
-                    }
-                    memberuid = sss_create_internal_fqname(tmp_ctx, memberuid,
-                                                           orig_dom->name);
-                    if (memberuid == NULL) {
-                        DEBUG(SSSDBG_OP_FAILURE,
-                              "sss_create_internal_fqname failed.\n");
-                        ret = ENOMEM;
-                        goto done;
-                    }
+                memberuid = sss_create_internal_fqname(tmp_ctx, memberuid,
+                                                       orig_dom->name);
+                if (memberuid == NULL) {
+                    DEBUG(SSSDBG_OP_FAILURE,
+                          "sss_create_internal_fqname failed.\n");
+                    ret = ENOMEM;
+                    goto done;
                 }
             }
         }
@@ -1521,9 +1512,6 @@ errno_t sysdb_add_group_member_overrides(struct 
sss_domain_info *domain,
         DEBUG(SSSDBG_TRACE_ALL, "Added [%s] to [%s].\n", memberuid,
                                 OVERRIDE_PREFIX SYSDB_MEMBERUID);
 
-        /* Free all temporary data of the current member to avoid memory usage
-         * spikes. All temporary data should be allocated below member_dn. */
-        talloc_free(member_dn);
     }
 
     ret = EOK;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 
1ae17969688fa29734ca14fd2b152decef1fdbca..4e84b3202cbf367e70a47a3c7edb06e357657538
 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -2976,7 +2976,12 @@ static int fill_grent(struct sss_packet *packet,
 
         memnum = 0;
         if (!dom->ignore_group_members) {
-            el = sss_view_ldb_msg_find_element(dom, msg, SYSDB_MEMBERUID);
+            /* unconditionally prefer OVERRIDE_PREFIX SYSDB_MEMBERUID, it
+             * might contain override names from the default view */
+            el = ldb_msg_find_element(msg, OVERRIDE_PREFIX SYSDB_MEMBERUID);
+            if (el == NULL) {
+                el = ldb_msg_find_element(msg, SYSDB_MEMBERUID);
+            }
             if (el) {
                 ret = fill_members(packet, nctx->rctx, dom, nctx, el,
                                    &rzero, &rsize, &memnum);
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index 
82a304feed864b09168d0f3e06a4e1bb120df7e4..892bebe63816a0dac0317dd1fd0135523f0e64d7
 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -1342,8 +1342,8 @@ static int test_nss_getgrnam_members_check(uint32_t 
status,
     int ret;
     uint32_t nmem;
     struct group gr;
-    const char *exp_members[] = { testmember1.pw_name,
-                                  testmember2.pw_name };
+    const char *exp_members[] = { testmember2.pw_name,
+                                  testmember1.pw_name };
     struct group expected = {
         .gr_gid = testgroup_members.gr_gid,
         .gr_name = testgroup_members.gr_name,
@@ -1429,10 +1429,10 @@ static int 
test_nss_getgrnam_members_check_fqdn(uint32_t status,
     assert_non_null(tmp_ctx);
 
     exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names,
-                                   nss_test_ctx->tctx->dom, 
testmember1.pw_name);
+                                   nss_test_ctx->tctx->dom, 
testmember2.pw_name);
     assert_non_null(exp_members[0]);
     exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names,
-                                   nss_test_ctx->tctx->dom, 
testmember2.pw_name);
+                                   nss_test_ctx->tctx->dom, 
testmember1.pw_name);
     assert_non_null(exp_members[1]);
 
     expected.gr_name = sss_tc_fqname(tmp_ctx,
@@ -1619,8 +1619,8 @@ static int test_nss_getgrnam_check_mix_dom(uint32_t 
status,
     tmp_ctx = talloc_new(nss_test_ctx);
     assert_non_null(tmp_ctx);
 
-    exp_members[0] = testmember1.pw_name;
-    exp_members[1] = testmember2.pw_name;
+    exp_members[0] = testmember2.pw_name;
+    exp_members[1] = testmember1.pw_name;
     exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names,
                                    nss_test_ctx->subdom, submember1.pw_name);
     assert_non_null(exp_members[2]);
@@ -1683,10 +1683,10 @@ static int 
test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status,
     assert_non_null(tmp_ctx);
 
     exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names,
-                                   nss_test_ctx->tctx->dom, 
testmember1.pw_name);
+                                   nss_test_ctx->tctx->dom, 
testmember2.pw_name);
     assert_non_null(exp_members[0]);
     exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names,
-                                   nss_test_ctx->tctx->dom, 
testmember2.pw_name);
+                                   nss_test_ctx->tctx->dom, 
testmember1.pw_name);
     assert_non_null(exp_members[1]);
     exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names,
                                    nss_test_ctx->subdom, submember1.pw_name);
@@ -1752,16 +1752,16 @@ static int test_nss_getgrnam_check_mix_subdom(uint32_t 
status,
     tmp_ctx = talloc_new(nss_test_ctx);
     assert_non_null(tmp_ctx);
 
-    exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names,
-                                   nss_test_ctx->subdom, submember1.pw_name);
-    assert_non_null(exp_members[0]);
     exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names,
-                                   nss_test_ctx->subdom, submember2.pw_name);
+                                   nss_test_ctx->subdom, submember1.pw_name);
     assert_non_null(exp_members[1]);
+    exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names,
+                                   nss_test_ctx->subdom, submember2.pw_name);
+    assert_non_null(exp_members[2]);
     /* Important: this member is from a non-qualified domain, so his name will
      * not be qualified either
      */
-    exp_members[2] = testmember1.pw_name;
+    exp_members[0] = testmember1.pw_name;
 
     expected.gr_name = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names,
                                      nss_test_ctx->subdom, 
testsubdomgroup.gr_name);
-- 
2.1.0

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to