[SSSD] [PATCHES] Make nss responder aware of views and overrides

Sumit Bose sbose at redhat.com
Fri Oct 17 12:08:40 UTC 2014


On Wed, Oct 15, 2014 at 01:08:29PM +0200, Sumit Bose wrote:
> On Tue, Oct 14, 2014 at 05:57:36PM +0200, Sumit Bose wrote:
> > Hi,
> > 
> > this patches make the nss responder view aware. A number of new sysdb
> > calls is added as drop in replacements from existing ones. I preferred
> > this instead of modifying the existing ones to not break their usage in
> > other places. But I think they are a good targets, together with the
> > other user and group related sysdb calls, for a refactoring in an
> > upcoming version.
> > 
> > bye,
> > Sumit
> 
> Please find attached a new version with some minor fixes in fill_pwent()
> and fill_grent() with respect to fully qualified names and an additional
> patch with the "changes" for the pam responder.

This new version contains fixes for memory leaks and unused return
values.

There are two new patches which make the enumeration requests view aware
as well.

bye,
Sumit
-------------- next part --------------
From 435fd321495e901751bdd956f92949b54f4baf9a Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 24 Sep 2014 13:01:20 +0200
Subject: [PATCH 01/15] confdb: add has_views and view_name to sss_domain_info

To let the responders know which view is applied and to make view
handling more efficiently especially when no view is applied/available
two new member are added to the sss_domain_info struct.

view_name is the name of the view if available. has_views is only true
if the client has a specific view applied, i.e. it is false for the case
when there are no views at all (e.g. plain LDAP provider) or the client
has the FreeIPA default view. This allows the responders to easily
bypass any view related code.
---
 src/confdb/confdb.c | 3 +++
 src/confdb/confdb.h | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index 0adff2b..8443fe5 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -1205,6 +1205,9 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
         goto done;
     }
 
+    domain->has_views = false;
+    domain->view_name = NULL;
+
     *_domain = domain;
     ret = EOK;
 done:
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 720b7dc..34d4610 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -255,6 +255,9 @@ struct sss_domain_info {
     char *forest;
     struct timeval subdomains_last_checked;
 
+    bool has_views;
+    char *view_name;
+
     struct sss_domain_info *prev;
     struct sss_domain_info *next;
 
-- 
1.8.3.1

-------------- next part --------------
From 07f85a31bd4a83e60c0cd57177e2490b5a36c1b0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 24 Sep 2014 13:03:53 +0200
Subject: [PATCH 02/15] new_subdomain: copy view data from parent

Since a view applies to the whole domain-subdomain tree the view data is
copied from the parent the new created domains.
---
 src/util/domain_info_utils.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 8ffbec2..4e2c14c 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -220,6 +220,17 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
     }
 
     dom->parent = parent;
+
+    /* Sub-domains always have the same view as the parent */
+    dom->has_views = parent->has_views;
+    if (parent->view_name != NULL) {
+        dom->view_name = talloc_strdup(dom, parent->view_name);
+        if (dom->view_name == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "Failed to copy parent's view name.\n");
+            goto fail;
+        }
+    }
+
     dom->name = talloc_strdup(dom, name);
     if (dom->name == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "Failed to copy domain name.\n");
-- 
1.8.3.1

-------------- next part --------------
From e3c5198210b751d536b755e92632960aa3095853 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 24 Sep 2014 13:35:29 +0200
Subject: [PATCH 03/15] sysdb: add view data to domains

The information about view is read from the cache and added to the
domain structs accordingly.
---
 src/db/sysdb_subdomains.c                | 106 +++++++++++++++++++++++++++++++
 src/tests/cmocka/test_responder_common.c |   7 ++
 2 files changed, 113 insertions(+)

diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index e0ad22f..e32b75f 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -175,6 +175,35 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
                     }
                 }
 
+                if (!dom->has_views && dom->view_name == NULL) {
+                    /* maybe views are not initialized, copy from parent */
+                    dom->has_views = dom->parent->has_views;
+                    if (dom->parent->view_name != NULL) {
+                        dom->view_name = talloc_strdup(dom,
+                                                       dom->parent->view_name);
+                        if (dom->view_name == NULL) {
+                            DEBUG(SSSDBG_OP_FAILURE,
+                                  "Failed to copy parent's view name.\n");
+                            ret = ENOMEM;
+                            goto done;
+                        }
+                    }
+                } else {
+                    if (dom->has_views != dom->parent->has_views
+                            || strcmp(dom->view_name,
+                                      dom->parent->view_name) != 0) {
+                        DEBUG(SSSDBG_CRIT_FAILURE,
+                            "Sub-domain [%s][%s] and parent [%s][%s] " \
+                            "views are different.\n",
+                            dom->has_views ? "has view" : "has no view",
+                            dom->view_name,
+                            dom->parent->has_views ? "has view" : "has no view",
+                            dom->parent->view_name);
+                        ret = EINVAL;
+                        goto done;
+                    }
+                }
+
                 break;
             }
         }
@@ -210,6 +239,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain)
                            SYSDB_SUBDOMAIN_ID,
                            SYSDB_SUBDOMAIN_FOREST,
                            NULL};
+    char *view_name = NULL;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -292,6 +322,82 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain)
         }
     }
 
+    ret = sysdb_get_view_name(tmp_ctx, domain->sysdb, &view_name);
+    if (ret != EOK && ret != ENOENT) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name failed.\n");
+        goto done;
+    }
+
+    if (ret == ENOENT || view_name == NULL
+            || (view_name != NULL
+                && strcmp(view_name, SYSDB_DEFAULT_VIEW_NAME) == 0)) {
+        /* handle default view */
+        if (domain->has_views) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "View name change is currently not supported. " \
+                  "New view is the default view while current view is [%s]. " \
+                  "View name is not changed!\n", domain->view_name);
+        } else {
+            if (domain->view_name == NULL) {
+                domain->view_name = talloc_strdup(domain,
+                                                  SYSDB_DEFAULT_VIEW_NAME);
+                if (domain->view_name == NULL) {
+                    DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
+                    ret = ENOMEM;
+                    goto done;
+                }
+            } else {
+                if (strcmp(domain->view_name, SYSDB_DEFAULT_VIEW_NAME) != 0) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "Domain [%s] has no view but view name [%s] " \
+                          "is not the default view name [%s].\n",
+                          domain->name, domain->view_name,
+                          SYSDB_DEFAULT_VIEW_NAME);
+                    ret = EINVAL;
+                    goto done;
+                }
+            }
+        }
+    } else {
+        /* handle view other than default */
+        if (domain->has_views) {
+            if (strcmp(domain->view_name, view_name) != 0) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "View name change is currently not supported. " \
+                      "New view is [%s] while current view is [%s]. " \
+                      "View name is not changed!\n",
+                      view_name, domain->view_name);
+            }
+        } else {
+            if (domain->view_name == NULL) {
+                domain->has_views = true;
+                domain->view_name = talloc_steal(domain, view_name);
+                if (domain->view_name == NULL) {
+                    DEBUG(SSSDBG_OP_FAILURE, "talloc_steal failed.\n");
+                    ret = ENOMEM;
+                    goto done;
+                }
+            } else {
+                if (strcmp(domain->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                        "View name change is currently not supported. " \
+                        "New view is [%s] while current is the default view. " \
+                        "View name is not changed!\n", view_name);
+                } else {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "Domain currently has no views, " \
+                          "but current view name is set to [%s] " \
+                          "and new view name is [%s].\n",
+                          domain->view_name, view_name);
+                    ret = EINVAL;
+                    goto done;
+                }
+            }
+        }
+    }
+
+    ret = EOK;
+
 done:
     talloc_free(tmp_ctx);
     return ret;
diff --git a/src/tests/cmocka/test_responder_common.c b/src/tests/cmocka/test_responder_common.c
index 7743760..a6f642a 100644
--- a/src/tests/cmocka/test_responder_common.c
+++ b/src/tests/cmocka/test_responder_common.c
@@ -87,6 +87,7 @@ struct parse_inp_test_ctx {
 void parse_inp_test_setup(void **state)
 {
     struct parse_inp_test_ctx *parse_inp_ctx;
+    int ret;
 
     assert_true(leak_check_setup());
     parse_inp_ctx = talloc_zero(global_talloc_context, struct parse_inp_test_ctx);
@@ -106,6 +107,12 @@ void parse_inp_test_setup(void **state)
     /* Testing the request race condition should be a special case */
     gettimeofday(&parse_inp_ctx->rctx->get_domains_last_call, NULL);
 
+    /* sysdb_master_domain_update sets the view name, if we do not call it
+     * here we get a leak check warning when sysdb_master_domain_update is
+     * called later while processing the tests. */
+    ret = sysdb_master_domain_update(parse_inp_ctx->tctx->dom);
+    assert_int_equal(ret, EOK);
+
     check_leaks_push(parse_inp_ctx);
     *state = parse_inp_ctx;
 }
-- 
1.8.3.1

-------------- next part --------------
From c65a68fe428b50e02a8e85559f5b445fd23debd6 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 25 Sep 2014 09:36:51 +0200
Subject: [PATCH 04/15] sysdb: add overide lookup calls

sysdb_search_user_override_by_name() and
sysdb_search_group_override_by_name() search for overrides in the given
view.

sysdb_add_overrides_to_object() adds the data from the override object
to the original object and makes them available for further processing.
---
 src/db/sysdb.h       |  24 ++++-
 src/db/sysdb_views.c | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/util.h      |   3 +
 3 files changed, 312 insertions(+), 1 deletion(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 6bb25de..8d4759e 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -43,6 +43,7 @@
 #define SYSDB_TMPL_NETGROUP_BASE SYSDB_NETGROUP_CONTAINER","SYSDB_DOM_BASE
 #define SYSDB_TMPL_RANGE_BASE SYSDB_RANGE_CONTAINER","SYSDB_BASE
 #define SYSDB_TMPL_VIEW_BASE SYSDB_VIEW_CONTAINER","SYSDB_BASE
+#define SYSDB_TMPL_VIEW_SEARCH_BASE "cn=%s,"SYSDB_TMPL_VIEW_BASE
 
 #define SYSDB_SUBDOMAIN_CLASS "subdomain"
 #define SYSDB_USER_CLASS "user"
@@ -199,12 +200,17 @@
                         SYSDB_PRIMARY_GROUP_GIDNUM, \
                         SYSDB_SID_STR, \
                         SYSDB_UPN, \
+                        SYSDB_OVERRIDE_DN, \
+                        SYSDB_DEFAULT_OVERRIDE_NAME, \
                         NULL}
 
 #define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
                            SYSDB_MEMBERUID, \
                            SYSDB_GHOST, \
                            SYSDB_DEFAULT_ATTRS, \
+                           SYSDB_SID_STR, \
+                           SYSDB_OVERRIDE_DN, \
+                           SYSDB_DEFAULT_OVERRIDE_NAME, \
                            NULL}
 
 #define SYSDB_NETGR_ATTRS {SYSDB_NAME, SYSDB_NETGROUP_TRIPLE, \
@@ -226,7 +232,7 @@
 #define SYSDB_TMPL_CUSTOM_SUBTREE "cn=%s,"SYSDB_TMPL_CUSTOM_BASE
 #define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE
 #define SYSDB_TMPL_RANGE SYSDB_NAME"=%s,"SYSDB_TMPL_RANGE_BASE
-#define SYSDB_TMPL_OVERRIDE SYSDB_OVERRIDE_ANCHOR_UUID"=%s,cn=%s,"SYSDB_TMPL_VIEW_BASE
+#define SYSDB_TMPL_OVERRIDE SYSDB_OVERRIDE_ANCHOR_UUID"=%s,"SYSDB_TMPL_VIEW_SEARCH_BASE
 
 #define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD
 #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE
@@ -438,6 +444,22 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
                                      struct sysdb_attrs *override_attrs,
                                      struct ldb_dn *obj_dn);
 
+errno_t sysdb_search_user_override_by_name(TALLOC_CTX *mem_ctx,
+                                           struct sss_domain_info *domain,
+                                           const char *name,
+                                           struct ldb_result **override_obj,
+                                           struct ldb_result **orig_obj);
+
+errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx,
+                                            struct sss_domain_info *domain,
+                                            const char *name,
+                                            struct ldb_result **override_obj,
+                                            struct ldb_result **orig_obj);
+
+errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
+                                      struct ldb_message *obj,
+                                      struct ldb_message *override_obj);
+
 /* Sysdb initialization.
  * call this function *only* once to initialize the database and get
  * the sysdb ctx */
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index c0fb915..92f4b47 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -371,6 +371,7 @@ errno_t sysdb_store_override(struct sss_domain_info *domain,
             goto done;
         }
 
+        /* TODO: add nameAlias for case-insentitive searches */
         for (c = 0; c < attrs->num; c++) {
             msg->elements[c] = attrs->a[c];
             msg->elements[c].flags = LDB_FLAG_MOD_ADD;
@@ -583,6 +584,7 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
     }
 
     for (c = 0; allowed_attrs[c] != NULL; c++) {
+        /* TODO: add nameAlias for case-insentitive searches */
         ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false,
                                      &el);
         if (ret == EOK) {
@@ -643,3 +645,287 @@ done:
     talloc_free(tmp_ctx);
     return ret;
 }
+
+
+#define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
+#define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
+
+enum override_object_type {
+    OO_TYPE_UNDEF = 0,
+    OO_TYPE_USER,
+    OO_TYPE_GROUP
+};
+
+static errno_t sysdb_search_override_by_name(TALLOC_CTX *mem_ctx,
+                                             struct sss_domain_info *domain,
+                                             const char *name,
+                                             enum override_object_type type,
+                                             struct ldb_result **override_obj,
+                                             struct ldb_result **orig_obj)
+{
+    TALLOC_CTX *tmp_ctx;
+    static const char *user_attrs[] = SYSDB_PW_ATTRS;
+    static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
+    const char **attrs;
+    struct ldb_dn *base_dn;
+    struct ldb_result *override_res;
+    struct ldb_result *orig_res;
+    char *sanitized_name;
+    char *lc_sanitized_name;
+    const char *src_name;
+    int ret;
+    const char *orig_obj_dn;
+    const char *filter;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
+                             SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
+    if (base_dn == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    /* If this is a subdomain we need to use fully qualified names for the
+     * search as well by default */
+    src_name = sss_get_domain_name(tmp_ctx, name, domain);
+    if (src_name == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_get_domain_name failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain,
+                                      &sanitized_name, &lc_sanitized_name);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize_for_dom failed.\n");
+        goto done;
+    }
+
+    switch(type) {
+    case OO_TYPE_USER:
+        filter = SYSDB_USER_NAME_OVERRIDE_FILTER;
+        attrs = user_attrs;
+        break;
+    case OO_TYPE_GROUP:
+        filter = SYSDB_GROUP_NAME_OVERRIDE_FILTER;
+        attrs = group_attrs;
+        break;
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected override object type [%d].\n",
+                                   type);
+        ret = EINVAL;
+        goto done;
+    }
+
+    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
+                     LDB_SCOPE_SUBTREE, attrs, filter,
+                     lc_sanitized_name,
+                     sanitized_name, sanitized_name);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    if (override_res->count == 0) {
+        DEBUG(SSSDBG_TRACE_FUNC, "No user override found for name [%s].\n",
+                                 name);
+        ret = ENOENT;
+        goto done;
+    } else if (override_res->count > 1) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Found more than one override for name [%s]\n.", name);
+        ret = EINVAL;
+        goto done;
+    }
+
+    if (orig_obj != NULL) {
+        orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
+                                                  SYSDB_OVERRIDE_OBJECT_DN,
+                                                  NULL);
+        if (orig_obj_dn == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Missing link to original object in override [%s].\n",
+                  ldb_dn_get_linearized(override_res->msgs[0]->dn));
+            ret = EINVAL;
+            goto done;
+        }
+
+        base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
+        if (base_dn == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
+                         LDB_SCOPE_BASE, attrs, NULL);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        *orig_obj = talloc_steal(mem_ctx, orig_res);
+    }
+
+
+    *override_obj = talloc_steal(mem_ctx, override_res);
+
+    ret = EOK;
+
+done:
+    talloc_zfree(tmp_ctx);
+    return ret;
+}
+
+errno_t sysdb_search_user_override_by_name(TALLOC_CTX *mem_ctx,
+                                           struct sss_domain_info *domain,
+                                           const char *name,
+                                           struct ldb_result **override_obj,
+                                           struct ldb_result **orig_obj)
+{
+    return sysdb_search_override_by_name(mem_ctx, domain, name, OO_TYPE_USER,
+                                         override_obj, orig_obj);
+}
+
+errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx,
+                                            struct sss_domain_info *domain,
+                                            const char *name,
+                                            struct ldb_result **override_obj,
+                                            struct ldb_result **orig_obj)
+{
+    return sysdb_search_override_by_name(mem_ctx, domain, name, OO_TYPE_GROUP,
+                                         override_obj, orig_obj);
+}
+
+/**
+ * @brief Add override data to the original object
+ *
+ * @param[in] domain Domain struct, needed to access the cache
+ * @oaram[in] obj The original object
+ * @param[in] override_obj The object with the override data, may be NULL
+ *
+ * @return EOK - Override data was added successfully
+ * @return ENOMEM - There was insufficient memory to complete the operation
+ * @return ENOENT - The original object did not have the SYSDB_OVERRIDE_DN
+ *                  attribute or the value of the attribute points an object
+ *                  which does not exists. Both conditions indicate that the
+ *                  cache must be refreshed.
+ */
+errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
+                                      struct ldb_message *obj,
+                                      struct ldb_message *override_obj)
+{
+    int ret;
+    const char *override_dn_str;
+    struct ldb_dn *override_dn;
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_result *res;
+    struct ldb_message *override;
+    uint64_t uid;
+    static const char *user_attrs[] = SYSDB_PW_ATTRS;
+    static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
+    const char **attrs;
+    struct attr_map {
+        const char *attr;
+        const char *new_attr;
+    } attr_map[] = {
+        {SYSDB_UIDNUM, OVERRIDE_PREFIX SYSDB_UIDNUM},
+        {SYSDB_GIDNUM, OVERRIDE_PREFIX SYSDB_GIDNUM},
+        {SYSDB_GECOS, OVERRIDE_PREFIX SYSDB_GECOS},
+        {SYSDB_HOMEDIR, OVERRIDE_PREFIX SYSDB_HOMEDIR},
+        {SYSDB_SHELL, OVERRIDE_PREFIX SYSDB_SHELL},
+        {SYSDB_NAME, OVERRIDE_PREFIX SYSDB_NAME},
+        {NULL, NULL}
+    };
+    size_t c;
+    const char *tmp_str;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    if (override_obj == NULL) {
+        override_dn_str = ldb_msg_find_attr_as_string(obj,
+                                                      SYSDB_OVERRIDE_DN, NULL);
+        if (override_dn_str == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Missing override DN for objext [%s].\n",
+                  ldb_dn_get_linearized(obj->dn));
+            ret = ENOENT;
+            goto done;
+        }
+
+        override_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, override_dn_str);
+        if (override_dn == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        if (ldb_dn_compare(obj->dn, override_dn) == 0) {
+            DEBUG(SSSDBG_TRACE_ALL, "Object [%s] has no overrides.\n",
+                                    ldb_dn_get_linearized(obj->dn));
+            ret = EOK;
+            goto done;
+        }
+
+        uid = ldb_msg_find_attr_as_uint64(obj, SYSDB_UIDNUM, 0);
+        if (uid == 0) {
+            /* No UID hence group object */
+            attrs = group_attrs;
+        } else {
+            attrs = user_attrs;
+        }
+
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, override_dn,
+                         LDB_SCOPE_BASE, attrs, NULL);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        if (res->count == 1) {
+            override = res->msgs[0];
+        } else if (res->count == 0) {
+            DEBUG(SSSDBG_TRACE_FUNC, "Override object [%s] does not exists.\n",
+                                     override_dn_str);
+            ret = ENOENT;
+            goto done;
+        } else {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Base search for override object returned [%d] results.\n",
+                  res->count);
+            ret = EINVAL;
+            goto done;
+        }
+    } else {
+        override = override_obj;
+    }
+
+    for (c = 0; attr_map[c].attr != NULL; c++) {
+        tmp_str = ldb_msg_find_attr_as_string(override, attr_map[c].attr, NULL);
+        if (tmp_str != NULL) {
+            talloc_steal(obj, tmp_str);
+            ret = ldb_msg_add_string(obj, attr_map[c].new_attr, tmp_str);
+            if (ret != LDB_SUCCESS) {
+                DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
+                ret = sysdb_error_to_errno(ret);
+                goto done;
+            }
+        }
+    }
+
+    ret = EOK;
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
diff --git a/src/util/util.h b/src/util/util.h
index 2b9f499..0ac9b01 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -546,6 +546,9 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx,
 
 #define IS_SUBDOMAIN(dom) ((dom)->parent != NULL)
 
+/* Currently views are only supported for subdomains */
+#define DOM_HAS_VIEWS(dom) ((dom)->has_views && IS_SUBDOMAIN(dom))
+
 errno_t sss_write_domain_mappings(struct sss_domain_info *domain);
 
 errno_t get_dom_names(TALLOC_CTX *mem_ctx,
-- 
1.8.3.1

-------------- next part --------------
From 65574f2372799ae13578cff42191967eee909cba Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 25 Sep 2014 09:38:26 +0200
Subject: [PATCH 05/15] sysdb: add sysdb_getpwnam/uid_with_views()

View-aware drop-in replacements for sysdb_getpwnam() and
sysdb_getpwuid().
---
 src/db/sysdb.h        |  24 +++++++++
 src/db/sysdb_search.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/db/sysdb_views.c  | 128 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 290 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 8d4759e..2db1a1c 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -201,6 +201,7 @@
                         SYSDB_SID_STR, \
                         SYSDB_UPN, \
                         SYSDB_OVERRIDE_DN, \
+                        SYSDB_OVERRIDE_OBJECT_DN, \
                         SYSDB_DEFAULT_OVERRIDE_NAME, \
                         NULL}
 
@@ -210,6 +211,7 @@
                            SYSDB_DEFAULT_ATTRS, \
                            SYSDB_SID_STR, \
                            SYSDB_OVERRIDE_DN, \
+                           SYSDB_OVERRIDE_OBJECT_DN, \
                            SYSDB_DEFAULT_OVERRIDE_NAME, \
                            NULL}
 
@@ -456,10 +458,32 @@ errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx,
                                             struct ldb_result **override_obj,
                                             struct ldb_result **orig_obj);
 
+errno_t sysdb_search_user_override_by_uid(TALLOC_CTX *mem_ctx,
+                                          struct sss_domain_info *domain,
+                                          uid_t uid,
+                                           struct ldb_result **override_obj,
+                                           struct ldb_result **orig_obj);
+
+errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
+                                            struct sss_domain_info *domain,
+                                            gid_t gid,
+                                            struct ldb_result **override_obj,
+                                            struct ldb_result **orig_obj);
+
 errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
                                       struct ldb_message *obj,
                                       struct ldb_message *override_obj);
 
+errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  const char *name,
+                                  struct ldb_result **res);
+
+errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  uid_t uid,
+                                  struct ldb_result **res);
+
 /* Sysdb initialization.
  * call this function *only* once to initialize the database and get
  * the sysdb ctx */
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index d51d213..d512643 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -83,6 +83,75 @@ done:
     return ret;
 }
 
+errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  const char *name,
+                                  struct ldb_result **res)
+{
+    int ret;
+    struct ldb_result *orig_obj = NULL;
+    struct ldb_result *override_obj = NULL;
+    TALLOC_CTX *tmp_ctx;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    /* If there are views we first have to search the overrides for matches */
+    if (DOM_HAS_VIEWS(domain)) {
+        ret = sysdb_search_user_override_by_name(tmp_ctx, domain, name,
+                                                 &override_obj, &orig_obj);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_search_override_by_name failed.\n");
+            goto done;
+        }
+    }
+
+    /* If there are no views or nothing was found in the overrides the
+     * original objects are searched. */
+    if (orig_obj == NULL) {
+        ret = sysdb_getpwnam(tmp_ctx, domain, name, &orig_obj);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwnam failed.\n");
+            goto done;
+        }
+    }
+
+    /* 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) {
+        ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
+                          override_obj == NULL ? NULL : override_obj ->msgs[0]);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
+            goto done;
+        }
+
+        if (ret == ENOENT) {
+            *res = talloc_zero(mem_ctx, struct ldb_result);
+            if (*res == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+                ret = ENOMEM;
+            } else {
+                ret = EOK;
+            }
+            goto done;
+        }
+    }
+
+    *res = talloc_steal(mem_ctx, orig_obj);
+    ret = EOK;
+    /* TODO: check if EOK is returned even if orig_obj is empty, i.e nothing
+     * found. */
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
                    struct sss_domain_info *domain,
                    uid_t uid,
@@ -121,6 +190,75 @@ done:
     return ret;
 }
 
+errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *domain,
+                                  uid_t uid,
+                                  struct ldb_result **res)
+{
+    int ret;
+    struct ldb_result *orig_obj = NULL;
+    struct ldb_result *override_obj = NULL;
+    TALLOC_CTX *tmp_ctx;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    /* If there are views we first have to search the overrides for matches */
+    if (DOM_HAS_VIEWS(domain)) {
+        ret = sysdb_search_user_override_by_uid(tmp_ctx, domain, uid,
+                                                &override_obj, &orig_obj);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_search_user_override_by_uid failed.\n");
+            goto done;
+        }
+    }
+
+    /* If there are no views or nothing was found in the overrides the
+     * original objects are searched. */
+    if (orig_obj == NULL) {
+        ret = sysdb_getpwuid(tmp_ctx, domain, uid, &orig_obj);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwuid failed.\n");
+            goto done;
+        }
+    }
+
+    /* 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) {
+        ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
+                           override_obj == NULL ? NULL : override_obj->msgs[0]);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
+            goto done;
+        }
+
+        if (ret == ENOENT) {
+            *res = talloc_zero(mem_ctx, struct ldb_result);
+            if (*res == NULL) {
+                DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+                ret = ENOMEM;
+            } else {
+                ret = EOK;
+            }
+            goto done;
+        }
+    }
+
+    *res = talloc_steal(mem_ctx, orig_obj);
+    ret = EOK;
+    /* TODO: check if EOK is returned even if orig_obj is empty, i.e nothing
+     * found. */
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
                     struct sss_domain_info *domain,
                     struct ldb_result **_res)
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index 92f4b47..4634181 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -648,7 +648,9 @@ done:
 
 
 #define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
+#define SYSDB_USER_UID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")("SYSDB_UIDNUM"=%lu))"
 #define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
+#define SYSDB_GROUP_GID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")("SYSDB_GIDNUM"=%lu))"
 
 enum override_object_type {
     OO_TYPE_UNDEF = 0,
@@ -802,6 +804,132 @@ errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx,
                                          override_obj, orig_obj);
 }
 
+static errno_t sysdb_search_override_by_id(TALLOC_CTX *mem_ctx,
+                                           struct sss_domain_info *domain,
+                                           unsigned long int id,
+                                           enum override_object_type type,
+                                           struct ldb_result **override_obj,
+                                           struct ldb_result **orig_obj)
+{
+    TALLOC_CTX *tmp_ctx;
+    static const char *user_attrs[] = SYSDB_PW_ATTRS;
+    static const char *group_attrs[] = SYSDB_GRSRC_ATTRS;
+    const char **attrs;
+    struct ldb_dn *base_dn;
+    struct ldb_result *override_res;
+    struct ldb_result *orig_res;
+    int ret;
+    const char *orig_obj_dn;
+    const char *filter;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
+                             SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name);
+    if (base_dn == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    switch(type) {
+    case OO_TYPE_USER:
+        filter = SYSDB_USER_UID_OVERRIDE_FILTER;
+        attrs = user_attrs;
+        break;
+    case OO_TYPE_GROUP:
+        filter = SYSDB_GROUP_GID_OVERRIDE_FILTER;
+        attrs = group_attrs;
+        break;
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected override object type [%d].\n",
+                                   type);
+        ret = EINVAL;
+        goto done;
+    }
+
+    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn,
+                     LDB_SCOPE_SUBTREE, attrs, filter, id);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    if (override_res->count == 0) {
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "No user override found for %s with id [%lu].\n",
+              (type == OO_TYPE_USER ? "user" : "group"), id);
+        ret = ENOENT;
+        goto done;
+    } else if (override_res->count > 1) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Found more than one override for id [%lu]\n.", id);
+        ret = EINVAL;
+        goto done;
+    }
+
+    if (orig_obj != NULL) {
+        orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0],
+                                                  SYSDB_OVERRIDE_OBJECT_DN,
+                                                  NULL);
+        if (orig_obj_dn == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Missing link to original object in override [%s].\n",
+                  ldb_dn_get_linearized(override_res->msgs[0]->dn));
+            ret = EINVAL;
+            goto done;
+        }
+
+        base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn);
+        if (base_dn == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn,
+                         LDB_SCOPE_BASE, attrs, NULL);
+        if (ret != LDB_SUCCESS) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        *orig_obj = talloc_steal(mem_ctx, orig_res);
+    }
+
+
+    *override_obj = talloc_steal(mem_ctx, override_res);
+
+    ret = EOK;
+
+done:
+    talloc_zfree(tmp_ctx);
+    return ret;
+}
+
+errno_t sysdb_search_user_override_by_uid(TALLOC_CTX *mem_ctx,
+                                          struct sss_domain_info *domain,
+                                          uid_t uid,
+                                           struct ldb_result **override_obj,
+                                           struct ldb_result **orig_obj)
+{
+    return sysdb_search_override_by_id(mem_ctx, domain, uid, OO_TYPE_USER,
+                                       override_obj, orig_obj);
+}
+
+errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
+                                            struct sss_domain_info *domain,
+                                            gid_t gid,
+                                            struct ldb_result **override_obj,
+                                            struct ldb_result **orig_obj)
+{
+    return sysdb_search_override_by_id(mem_ctx, domain, gid, OO_TYPE_GROUP,
+                                       override_obj, orig_obj);
+}
+
 /**
  * @brief Add override data to the original object
  *
-- 
1.8.3.1

-------------- next part --------------
From 8d4b7038e08e367cc99b5fb275af216f124e1a15 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 26 Sep 2014 20:09:25 +0200
Subject: [PATCH 06/15] sysdb: add
 sss_view_ldb_msg_find_element/attr_as_string/uint64

Override-aware replacements for the corresponding ldb_msg_find_* calls.
First it is check if an override value is available before the original
value is returned.
---
 src/db/sysdb.h       |  15 +++++++
 src/db/sysdb_views.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 2db1a1c..8d2894a 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -484,6 +484,21 @@ errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx,
                                   uid_t uid,
                                   struct ldb_result **res);
 
+struct ldb_message_element *
+sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
+                              const struct ldb_message *msg,
+                              const char *attr_name);
+
+const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
+                                                 const struct ldb_message *msg,
+                                                 const char *attr_name,
+                                                 const char * default_value);
+
+uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom,
+                                              const struct ldb_message *msg,
+                                              const char *attr_name,
+                                              uint64_t default_value);
+
 /* Sysdb initialization.
  * call this function *only* once to initialize the database and get
  * the sysdb ctx */
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index 4634181..aa6d53c 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -1057,3 +1057,119 @@ done:
     return ret;
 }
 
+struct ldb_message_element *
+sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
+                                              const struct ldb_message *msg,
+                                              const char *attr_name)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    struct ldb_message_element *val;
+    char *override_attr_name;
+
+    if (DOM_HAS_VIEWS(dom)) {
+        tmp_ctx = talloc_new(NULL);
+        if (tmp_ctx == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+            val = NULL;
+            goto done;
+        }
+
+        override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
+                                                              attr_name);
+        if (override_attr_name == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
+            val = NULL;
+            goto done;
+        }
+
+        val = ldb_msg_find_element(msg, override_attr_name);
+        if (val != NULL) {
+            goto done;
+        }
+    }
+
+    val = ldb_msg_find_element(msg, attr_name);
+
+done:
+    talloc_free(tmp_ctx);
+    return val;
+}
+
+uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom,
+                                              const struct ldb_message *msg,
+                                              const char *attr_name,
+                                              uint64_t default_value)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    uint64_t val;
+    char *override_attr_name;
+
+    if (DOM_HAS_VIEWS(dom)) {
+        tmp_ctx = talloc_new(NULL);
+        if (tmp_ctx == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+            val = default_value;
+            goto done;
+        }
+
+        override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
+                                                              attr_name);
+        if (override_attr_name == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
+            val = default_value;
+            goto done;
+        }
+
+        if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
+            val = ldb_msg_find_attr_as_uint64(msg, override_attr_name,
+                                              default_value);
+            goto done;
+        }
+    }
+
+    val = ldb_msg_find_attr_as_uint64(msg, attr_name, default_value);
+
+done:
+    talloc_free(tmp_ctx);
+    return val;
+}
+
+const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
+                                                 const struct ldb_message *msg,
+                                                 const char *attr_name,
+                                                 const char * default_value)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    const char *val;
+    char *override_attr_name;
+
+    if (DOM_HAS_VIEWS(dom)) {
+        tmp_ctx = talloc_new(NULL);
+        if (tmp_ctx == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+            val = default_value;
+            goto done;
+        }
+
+        override_attr_name = talloc_asprintf(tmp_ctx, "%s%s", OVERRIDE_PREFIX,
+                                                              attr_name);
+        if (override_attr_name == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
+            val = default_value;
+            goto done;
+        }
+
+        if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
+            val = ldb_msg_find_attr_as_string(msg, override_attr_name,
+                                              default_value);
+            goto done;
+        }
+    }
+
+    val = ldb_msg_find_attr_as_string(msg, attr_name, default_value);
+
+done:
+    talloc_free(tmp_ctx);
+    return val;
+}
+
-- 
1.8.3.1

-------------- next part --------------
From 662136ce5f8baa0243df1648eb0b05de320242a2 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 25 Sep 2014 09:38:44 +0200
Subject: [PATCH 07/15] nss: add view support for getpwnam/getpwuid requests

For user lookups view and override aware calls to search the cache and
read attribute values are used.

Relates to https://fedorahosted.org/sssd/ticket/2375
---
 src/responder/nss/nsssrv_cmd.c | 132 ++++++++++++++++++++++++++++++-----------
 1 file changed, 99 insertions(+), 33 deletions(-)

diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 78ef1c5..99d44e5 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -339,9 +339,54 @@ static int fill_pwent(struct sss_packet *packet,
         msg = msgs[i];
 
         upn = ldb_msg_find_attr_as_string(msg, SYSDB_UPN, NULL);
-        orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
-        uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
-        gid = get_gid_override(msg, dom);
+
+        if (DOM_HAS_VIEWS(dom)) {
+            orig_name = ldb_msg_find_attr_as_string(msg,
+                                                    OVERRIDE_PREFIX SYSDB_NAME,
+                                                    NULL);
+            if (orig_name != NULL && IS_SUBDOMAIN(dom)) {
+                /* Override names are not fully qualified */
+                add_domain = true;
+            }
+            uid = ldb_msg_find_attr_as_uint64(msg,
+                                              OVERRIDE_PREFIX SYSDB_UIDNUM, 0);
+            gid = ldb_msg_find_attr_as_uint64(msg,
+                                              OVERRIDE_PREFIX SYSDB_GIDNUM, 0);
+            tmpstr = ldb_msg_find_attr_as_string(msg,
+                                                OVERRIDE_PREFIX SYSDB_GECOS,
+                                                NULL);
+            to_sized_string(&gecos, tmpstr);
+            tmpstr = ldb_msg_find_attr_as_string(msg,
+                                                  OVERRIDE_PREFIX SYSDB_HOMEDIR,
+                                                  NULL);
+            to_sized_string(&homedir, tmpstr);
+            tmpstr = ldb_msg_find_attr_as_string(msg,
+                                                    OVERRIDE_PREFIX SYSDB_SHELL,
+                                                    NULL);
+            to_sized_string(&shell, tmpstr);
+        } else {
+            orig_name = NULL;
+            uid = 0;
+            gid = 0;
+            ZERO_STRUCT(gecos);
+            ZERO_STRUCT(homedir);
+            ZERO_STRUCT(shell);
+        }
+
+        if (orig_name == NULL) {
+            orig_name = ldb_msg_find_attr_as_string(msg,
+                                                    SYSDB_DEFAULT_OVERRIDE_NAME,
+                                                    NULL);
+            if (orig_name == NULL) {
+                orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+            }
+        }
+        if (uid == 0) {
+            uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
+        }
+        if (gid == 0) {
+            gid = get_gid_override(msg, dom);
+        }
 
         if (!orig_name || !uid || !gid) {
             DEBUG(SSSDBG_OP_FAILURE, "Incomplete user object for %s[%llu]! Skipping\n",
@@ -385,31 +430,38 @@ static int fill_pwent(struct sss_packet *packet,
 
         to_sized_string(&name, tmpstr);
 
-        tmpstr = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
-        if (!tmpstr) {
-            to_sized_string(&gecos, "");
-        } else {
-            to_sized_string(&gecos, tmpstr);
+        if (gecos.str == NULL) {
+            tmpstr = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
+            if (!tmpstr) {
+                to_sized_string(&gecos, "");
+            } else {
+                to_sized_string(&gecos, tmpstr);
+            }
         }
 
-        ZERO_STRUCT(homedir_ctx);
+        if (homedir.str == NULL) {
+            ZERO_STRUCT(homedir_ctx);
 
-        homedir_ctx.username = name.str;
-        homedir_ctx.uid = uid;
-        homedir_ctx.domain = dom->name;
-        homedir_ctx.upn = upn;
+            homedir_ctx.username = name.str;
+            homedir_ctx.uid = uid;
+            homedir_ctx.domain = dom->name;
+            homedir_ctx.upn = upn;
 
-        tmpstr = get_homedir_override(tmp_ctx, msg, nctx, dom, &homedir_ctx);
-        if (!tmpstr) {
-            to_sized_string(&homedir, "/");
-        } else {
-            to_sized_string(&homedir, tmpstr);
+            tmpstr = get_homedir_override(tmp_ctx, msg, nctx, dom, &homedir_ctx);
+            if (!tmpstr) {
+                to_sized_string(&homedir, "/");
+            } else {
+                to_sized_string(&homedir, tmpstr);
+            }
         }
-        tmpstr = get_shell_override(tmp_ctx, msg, nctx, dom);
-        if (!tmpstr) {
-            to_sized_string(&shell, "");
-        } else {
-            to_sized_string(&shell, tmpstr);
+
+        if (shell.str == NULL) {
+            tmpstr = get_shell_override(tmp_ctx, msg, nctx, dom);
+            if (!tmpstr) {
+                to_sized_string(&shell, "");
+            } else {
+                to_sized_string(&shell, tmpstr);
+            }
         }
 
         rsize = 2 * sizeof(uint32_t) + name.len + gecos.len +
@@ -734,6 +786,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
     int ret;
     static const char *user_attrs[] = SYSDB_PW_ATTRS;
     struct ldb_message *msg;
+    const char *extra_flag = NULL;
 
     nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
 
@@ -827,7 +880,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
                 dctx->res->msgs[0] = talloc_steal(dctx->res->msgs, msg);
             }
         } else {
-            ret = sysdb_getpwnam(cmdctx, dom, name, &dctx->res);
+            ret = sysdb_getpwnam_with_views(cmdctx, dom, name, &dctx->res);
         }
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
@@ -871,11 +924,17 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
         /* if this is a caching provider (or if we haven't checked the cache
          * yet) then verify that the cache is uptodate */
         if (dctx->check_provider) {
-            ret = check_cache(dctx, nctx, dctx->res,
-                              SSS_DP_USER, name, 0,
-                              cmdctx->name_is_upn ? EXTRA_NAME_IS_UPN : NULL,
-                              nss_cmd_getby_dp_callback,
-                              dctx);
+
+            if (cmdctx->name_is_upn) {
+                extra_flag = EXTRA_NAME_IS_UPN;
+            } else if (DOM_HAS_VIEWS(dom) && dctx->res->count == 0) {
+                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+            } else {
+                extra_flag = NULL;
+            }
+
+            ret = check_cache(dctx, nctx, dctx->res, SSS_DP_USER, name, 0,
+                              extra_flag, nss_cmd_getby_dp_callback, dctx);
             if (ret != EOK) {
                 /* Anything but EOK means we should reenter the mainloop
                  * because we may be refreshing the cache
@@ -1453,6 +1512,7 @@ static int nss_cmd_getpwuid_search(struct nss_dom_ctx *dctx)
     struct nss_ctx *nctx;
     int ret;
     int err;
+    const char *extra_flag = NULL;
 
     nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
 
@@ -1492,7 +1552,7 @@ static int nss_cmd_getpwuid_search(struct nss_dom_ctx *dctx)
             goto done;
         }
 
-        ret = sysdb_getpwuid(cmdctx, dom, cmdctx->id, &dctx->res);
+        ret = sysdb_getpwuid_with_views(cmdctx, dom, cmdctx->id, &dctx->res);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Failed to make request to our cache!\n");
@@ -1523,9 +1583,15 @@ static int nss_cmd_getpwuid_search(struct nss_dom_ctx *dctx)
         /* if this is a caching provider (or if we haven't checked the cache
          * yet) then verify that the cache is uptodate */
         if (dctx->check_provider) {
-            ret = check_cache(dctx, nctx, dctx->res,
-                              SSS_DP_USER, NULL, cmdctx->id, NULL,
-                              nss_cmd_getby_dp_callback,
+
+            if (DOM_HAS_VIEWS(dom) && dctx->res->count == 0) {
+                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+            } else {
+                extra_flag = NULL;
+            }
+
+            ret = check_cache(dctx, nctx, dctx->res, SSS_DP_USER, NULL,
+                              cmdctx->id, extra_flag, nss_cmd_getby_dp_callback,
                               dctx);
             if (ret != EOK) {
                 /* Anything but EOK means we should reenter the mainloop
-- 
1.8.3.1

-------------- next part --------------
From dd438a880ab248f1c72cc46264c728e35e34692f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 26 Sep 2014 14:01:04 +0200
Subject: [PATCH 08/15] sysdb: add sysdb_initgroups_with_views()

---
 src/db/sysdb.h        |   6 +++
 src/db/sysdb_search.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 8d2894a..b65fa1d 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -226,6 +226,7 @@
                             SYSDB_ORIG_DN, \
                             SYSDB_SID_STR, \
                             SYSDB_NAME, \
+                            SYSDB_OVERRIDE_DN, \
                             NULL}
 
 #define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE
@@ -565,6 +566,11 @@ int sysdb_initgroups(TALLOC_CTX *mem_ctx,
                      const char *name,
                      struct ldb_result **res);
 
+int sysdb_initgroups_with_views(TALLOC_CTX *mem_ctx,
+                                struct sss_domain_info *domain,
+                                const char *name,
+                                struct ldb_result **res);
+
 int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
                         struct sss_domain_info *domain,
                         const char *name,
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index d512643..cbabee9 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -607,6 +607,119 @@ done:
     return ret;
 }
 
+int sysdb_initgroups_with_views(TALLOC_CTX *mem_ctx,
+                                struct sss_domain_info *domain,
+                                const char *name,
+                                struct ldb_result **_res)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_result *res;
+    struct ldb_dn *user_dn;
+    struct ldb_request *req;
+    struct ldb_control **ctrl;
+    struct ldb_asq_control *control;
+    static const char *attrs[] = SYSDB_INITGR_ATTRS;
+    int ret;
+    size_t c;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    ret = sysdb_getpwnam_with_views(tmp_ctx, domain, name, &res);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_getpwnam failed: [%d][%s]\n",
+                  ret, strerror(ret));
+        goto done;
+    }
+
+    if (res->count == 0) {
+        /* User is not cached yet */
+        *_res = talloc_steal(mem_ctx, res);
+        ret = EOK;
+        goto done;
+
+    } else if (res->count != 1) {
+        ret = EIO;
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "sysdb_getpwnam returned count: [%d]\n", res->count);
+        goto done;
+    }
+
+    /* no need to steal the dn, we are not freeing the result */
+    user_dn = res->msgs[0]->dn;
+
+    /* note we count on the fact that the default search callback
+     * will just keep appending values. This is by design and can't
+     * change so it is ok to already have a result (from the getpwnam)
+     * even before we call the next search */
+
+    ctrl = talloc_array(tmp_ctx, struct ldb_control *, 2);
+    if (!ctrl) {
+        ret = ENOMEM;
+        goto done;
+    }
+    ctrl[1] = NULL;
+    ctrl[0] = talloc(ctrl, struct ldb_control);
+    if (!ctrl[0]) {
+        ret = ENOMEM;
+        goto done;
+    }
+    ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
+    ctrl[0]->critical = 1;
+    control = talloc(ctrl[0], struct ldb_asq_control);
+    if (!control) {
+        ret = ENOMEM;
+        goto done;
+    }
+    control->request = 1;
+    control->source_attribute = talloc_strdup(control, SYSDB_INITGR_ATTR);
+    if (!control->source_attribute) {
+        ret = ENOMEM;
+        goto done;
+    }
+    control->src_attr_len = strlen(control->source_attribute);
+    ctrl[0]->data = control;
+
+    ret = ldb_build_search_req(&req, domain->sysdb->ldb, tmp_ctx,
+                               user_dn, LDB_SCOPE_BASE,
+                               SYSDB_INITGR_FILTER, attrs, ctrl,
+                               res, ldb_search_default_callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    ret = ldb_request(domain->sysdb->ldb, req);
+    if (ret == LDB_SUCCESS) {
+        ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+    }
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    if (DOM_HAS_VIEWS(domain)) {
+        /* Skip user entry because it already has override values added */
+        for (c = 1; c < res->count; c++) {
+            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                      "sysdb_add_overrides_to_object failed.\n");
+                goto done;
+            }
+        }
+    }
+
+    *_res = talloc_steal(mem_ctx, res);
+
+done:
+    talloc_zfree(tmp_ctx);
+    return ret;
+}
+
 int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
                         struct sss_domain_info *domain,
                         const char *name,
-- 
1.8.3.1

-------------- next part --------------
From 39172decf74ccae08e2fa3ec005daa1dfaf564f1 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 26 Sep 2014 20:16:51 +0200
Subject: [PATCH 09/15] nss: add view support to initgroups request

Make sysdb request view and override aware.

Relates to https://fedorahosted.org/sssd/ticket/2375
---
 src/responder/nss/nsssrv_cmd.c | 51 ++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 14 deletions(-)

diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 99d44e5..11cdfe7 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -3802,7 +3802,8 @@ done:
 
 /* FIXME: what about mpg, should we return the user's GID ? */
 /* FIXME: should we filter out GIDs ? */
-static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
+static int fill_initgr(struct sss_packet *packet, struct sss_domain_info *dom,
+                       struct ldb_result *res)
 {
     uint8_t *body;
     size_t blen;
@@ -3826,14 +3827,15 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
     }
     sss_packet_get_body(packet, &body, &blen);
 
-    orig_primary_gid = ldb_msg_find_attr_as_uint64(res->msgs[0],
-                                                   SYSDB_PRIMARY_GROUP_GIDNUM,
-                                                   0);
+    orig_primary_gid = sss_view_ldb_msg_find_attr_as_uint64(dom, res->msgs[0],
+                                                     SYSDB_PRIMARY_GROUP_GIDNUM,
+                                                     0);
 
     /* If the GID of the original primary group is available but equal to the
     * current primary GID it must not be added. */
     if (orig_primary_gid != 0) {
-        gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
+        gid = sss_view_ldb_msg_find_attr_as_uint64(dom, res->msgs[0],
+                                                   SYSDB_GIDNUM, 0);
 
         if (orig_primary_gid == gid) {
             orig_primary_gid = 0;
@@ -3846,8 +3848,10 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
 
     /* skip first entry, it's the user entry */
     for (i = 0; i < num; i++) {
-        gid = ldb_msg_find_attr_as_uint64(res->msgs[i + 1], SYSDB_GIDNUM, 0);
-        posix = ldb_msg_find_attr_as_string(res->msgs[i + 1], SYSDB_POSIX, NULL);
+        gid = sss_view_ldb_msg_find_attr_as_uint64(dom, res->msgs[i + 1],
+                                                   SYSDB_GIDNUM, 0);
+        posix = ldb_msg_find_attr_as_string(res->msgs[i + 1],
+                                            SYSDB_POSIX, NULL);
         if (!gid) {
             if (posix && strcmp(posix, "FALSE") == 0) {
                 skipped++;
@@ -3898,7 +3902,7 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx)
         return EFAULT;
     }
 
-    ret = fill_initgr(cctx->creq->out, dctx->res);
+    ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res);
     if (ret) {
         return ret;
     }
@@ -3918,6 +3922,8 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
     static const char *user_attrs[] = SYSDB_PW_ATTRS;
     struct ldb_message *msg;
     const char *sysdb_name;
+    size_t c;
+    const char *extra_flag = NULL;
 
     nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
 
@@ -3997,8 +4003,19 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
             }
 
             ret = sysdb_initgroups(cmdctx, dom, sysdb_name, &dctx->res);
+            if (ret == EOK && DOM_HAS_VIEWS(dom)) {
+                for (c = 0; c < dctx->res->count; c++) {
+                    ret = sysdb_add_overrides_to_object(dom, dctx->res->msgs[c],
+                                                        NULL);
+                    if (ret != EOK) {
+                        DEBUG(SSSDBG_OP_FAILURE,
+                              "sysdb_add_overrides_to_object failed.\n");
+                        return ret;
+                    }
+                }
+            }
         } else {
-            ret = sysdb_initgroups(cmdctx, dom, name, &dctx->res);
+            ret = sysdb_initgroups_with_views(cmdctx, dom, name, &dctx->res);
         }
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
@@ -4029,11 +4046,17 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
         /* if this is a caching provider (or if we haven't checked the cache
          * yet) then verify that the cache is uptodate */
         if (dctx->check_provider) {
-            ret = check_cache(dctx, nctx, dctx->res,
-                              SSS_DP_INITGROUPS, name, 0,
-                              cmdctx->name_is_upn ? EXTRA_NAME_IS_UPN : NULL,
-                              nss_cmd_getby_dp_callback,
-                              dctx);
+
+            if (cmdctx->name_is_upn) {
+                extra_flag = EXTRA_NAME_IS_UPN;
+            } else if (DOM_HAS_VIEWS(dom) && dctx->res->count == 0) {
+                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+            } else {
+                extra_flag = NULL;
+            }
+
+            ret = check_cache(dctx, nctx, dctx->res, SSS_DP_INITGROUPS, name, 0,
+                              extra_flag, nss_cmd_getby_dp_callback, dctx);
             if (ret != EOK) {
                 /* Anything but EOK means we should reenter the mainloop
                  * because we may be refreshing the cache
-- 
1.8.3.1

-------------- next part --------------
From ae947485ccd95196d9e24a4dbedc3e7e9593b07f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 29 Sep 2014 12:12:01 +0200
Subject: [PATCH 10/15] sysdb: add sysdb_getgrnam_with_views and
 sysdb_getgrgid_with_views

---
 src/db/sysdb.h        |  13 ++++
 src/db/sysdb_search.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/db/sysdb_views.c  | 130 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 315 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index b65fa1d..f7e507c 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -475,6 +475,9 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
                                       struct ldb_message *obj,
                                       struct ldb_message *override_obj);
 
+errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
+                                         struct ldb_message *obj);
+
 errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx,
                                   struct sss_domain_info *domain,
                                   const char *name,
@@ -485,6 +488,16 @@ errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx,
                                   uid_t uid,
                                   struct ldb_result **res);
 
+int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx,
+                              struct sss_domain_info *domain,
+                              const char *name,
+                              struct ldb_result **res);
+
+int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx,
+                              struct sss_domain_info *domain,
+                              gid_t gid,
+                              struct ldb_result **res);
+
 struct ldb_message_element *
 sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
                               const struct ldb_message *msg,
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index cbabee9..4077dd4 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -339,6 +339,92 @@ static int mpg_res_convert(struct ldb_result *res)
     return EOK;
 }
 
+int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx,
+                              struct sss_domain_info *domain,
+                              const char *name,
+                              struct ldb_result **res)
+{
+    TALLOC_CTX *tmp_ctx;
+    int ret;
+    struct ldb_result *orig_obj = NULL;
+    struct ldb_result *override_obj = NULL;
+    struct ldb_message_element *el;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    /* If there are views we first have to search the overrides for matches */
+    if (DOM_HAS_VIEWS(domain)) {
+        ret = sysdb_search_group_override_by_name(tmp_ctx, domain, name,
+                                                  &override_obj, &orig_obj);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_search_group_override_by_name failed.\n");
+            goto done;
+        }
+    }
+
+    /* If there are no views or nothing was found in the overrides the
+     * original objects are searched. */
+    if (orig_obj == NULL) {
+        ret = sysdb_getgrnam(tmp_ctx, domain, name, &orig_obj);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_getgrnam failed.\n");
+            goto done;
+        }
+    }
+
+    /* 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) {
+        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]);
+        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]);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_add_group_member_overrides failed.\n");
+            goto done;
+        }
+    }
+
+    *res = talloc_steal(mem_ctx, orig_obj);
+    ret = EOK;
+    /* TODO: check if EOK is returned even if orig_obj is empty, i.e nothing
+     * found. */
+
+done:
+    if (ret == ENOENT) {
+        DEBUG(SSSDBG_TRACE_ALL, "Returning empty result.\n");
+        *res = talloc_zero(mem_ctx, struct ldb_result);
+        if (*res == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+            ret = ENOMEM;
+        } else {
+            ret = EOK;
+        }
+    }
+
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
                    struct sss_domain_info *domain,
                    const char *name,
@@ -407,6 +493,92 @@ done:
     return ret;
 }
 
+int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx,
+                              struct sss_domain_info *domain,
+                              gid_t gid,
+                              struct ldb_result **res)
+{
+    TALLOC_CTX *tmp_ctx;
+    int ret;
+    struct ldb_result *orig_obj = NULL;
+    struct ldb_result *override_obj = NULL;
+    struct ldb_message_element *el;
+
+    tmp_ctx = talloc_new(NULL);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    /* If there are views we first have to search the overrides for matches */
+    if (DOM_HAS_VIEWS(domain)) {
+        ret = sysdb_search_group_override_by_gid(tmp_ctx, domain, gid,
+                                                 &override_obj, &orig_obj);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_search_group_override_by_gid failed.\n");
+            goto done;
+        }
+    }
+
+    /* If there are no views or nothing was found in the overrides the
+     * original objects are searched. */
+    if (orig_obj == NULL) {
+        ret = sysdb_getgrgid(tmp_ctx, domain, gid, &orig_obj);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_getgrgid failed.\n");
+            goto done;
+        }
+    }
+
+    /* 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) {
+        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]);
+        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]);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_add_group_member_overrides failed.\n");
+            goto done;
+        }
+    }
+
+    *res = talloc_steal(mem_ctx, orig_obj);
+    ret = EOK;
+    /* TODO: check if EOK is returned even if orig_obj is empty, i.e nothing
+     * found. */
+
+done:
+    if (ret == ENOENT) {
+        DEBUG(SSSDBG_TRACE_ALL, "Returning empty result.\n");
+        *res = talloc_zero(mem_ctx, struct ldb_result);
+        if (*res == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
+            ret = ENOMEM;
+        } else {
+            ret = EOK;
+        }
+    }
+
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
                    struct sss_domain_info *domain,
                    gid_t gid,
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index aa6d53c..62b131f 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -1057,6 +1057,136 @@ done:
     return ret;
 }
 
+errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
+                                         struct ldb_message *obj)
+{
+    int ret;
+    size_t c;
+    struct ldb_message_element *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;
+    struct ldb_dn *override_dn;
+    const char *memberuid;
+
+    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");
+        ret = ENOMEM;
+        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 = 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;
+        }
+
+        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;
+        }
+
+        override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0],
+                                                      SYSDB_OVERRIDE_DN, NULL);
+        if (override_dn_str == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Missing override DN for objext [%s].\n",
+                  ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+            ret = ENOENT;
+            goto done;
+        }
+
+        override_dn = ldb_dn_new(member_obj, domain->sysdb->ldb,
+                                 override_dn_str);
+        if (override_dn == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        memberuid = NULL;
+        if (ldb_dn_compare(member_obj->msgs[0]->dn, override_dn) != 0) {
+            DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n",
+                  ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+
+            ret = ldb_search(domain->sysdb->ldb, member_obj, &override_obj,
+                             override_dn, LDB_SCOPE_BASE, member_attrs, NULL);
+            if (ret != LDB_SUCCESS) {
+                ret = sysdb_error_to_errno(ret);
+                goto done;
+            }
+
+            if (override_obj->count != 1) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                     "Base search for override object returned [%d] results.\n",
+                     member_obj->count);
+                ret = EINVAL;
+                goto done;
+            }
+
+            memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0],
+                                                    SYSDB_NAME,
+                                                    NULL);
+        }
+
+        if (memberuid == NULL) {
+            DEBUG(SSSDBG_TRACE_ALL, "No override name available.\n");
+
+            memberuid = ldb_msg_find_attr_as_string(member_obj->msgs[0],
+                                                    SYSDB_NAME,
+                                                    NULL);
+            if (memberuid == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n",
+                      ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+                ret = EINVAL;
+                goto done;
+            }
+        }
+
+        ret = ldb_msg_add_string(obj, OVERRIDE_PREFIX SYSDB_MEMBERUID,
+                                 memberuid);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        /* 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;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
 struct ldb_message_element *
 sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
                                               const struct ldb_message *msg,
-- 
1.8.3.1

-------------- next part --------------
From 0b3e297db6cb2cf0fbb1a781fe5093a25ae0d25d Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 29 Sep 2014 14:52:03 +0200
Subject: [PATCH 11/15] nss: add view support for getgr* requests

Make group lookups view and override aware.

Relates to https://fedorahosted.org/sssd/ticket/2375
---
 src/responder/nss/nsssrv_cmd.c | 63 +++++++++++++++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 11cdfe7..9e827e6 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -2637,7 +2637,7 @@ static int fill_grent(struct sss_packet *packet,
     size_t blen;
     uint32_t gid;
     const char *tmpstr;
-    const char *orig_name;
+    const char *orig_name = NULL;
     struct sized_string name;
     struct sized_string pwfield;
     struct sized_string fullname;
@@ -2680,8 +2680,25 @@ static int fill_grent(struct sss_packet *packet,
         rsize = 0;
 
         /* find group name/gid */
-        orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
-        gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
+        if (DOM_HAS_VIEWS(dom)) {
+            orig_name = ldb_msg_find_attr_as_string(msg,
+                                                    OVERRIDE_PREFIX SYSDB_NAME,
+                                                    NULL);
+            if (orig_name != NULL && IS_SUBDOMAIN(dom)) {
+                /* Override names are not fully qualified */
+                add_domain = true;
+            }
+        }
+        if (orig_name == NULL) {
+            orig_name = ldb_msg_find_attr_as_string(msg,
+                                                    SYSDB_DEFAULT_OVERRIDE_NAME,
+                                                    NULL);
+            if (orig_name == NULL) {
+                orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+            }
+        }
+
+        gid = sss_view_ldb_msg_find_attr_as_uint64(dom, msg, SYSDB_GIDNUM, 0);
         if (!orig_name || !gid) {
             DEBUG(SSSDBG_OP_FAILURE,
                   "Incomplete group object for %s[%llu]! Skipping\n",
@@ -2773,7 +2790,7 @@ static int fill_grent(struct sss_packet *packet,
 
         memnum = 0;
         if (!dom->ignore_group_members) {
-            el = ldb_msg_find_element(msg, SYSDB_MEMBERUID);
+            el = sss_view_ldb_msg_find_element(dom, msg, SYSDB_MEMBERUID);
             if (el) {
                 ret = fill_members(packet, dom, nctx, el, &rzero, &rsize,
                                    &memnum);
@@ -2785,6 +2802,13 @@ static int fill_grent(struct sss_packet *packet,
             }
             el = ldb_msg_find_element(msg, SYSDB_GHOST);
             if (el) {
+                if (DOM_HAS_VIEWS(dom) && el->num_values != 0) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "Domain has a view [%s] but group [%s] still has " \
+                          "ghost members.\n", dom->view_name, orig_name);
+                    num = 0;
+                    goto done;
+                }
                 ret = fill_members(packet, dom, nctx, el, &rzero, &rsize,
                                    &memnum);
                 if (ret != EOK) {
@@ -2884,6 +2908,7 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
     char *name = NULL;
     struct nss_ctx *nctx;
     int ret;
+    const char *extra_flag = NULL;
 
     nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
 
@@ -2947,7 +2972,7 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
             return EIO;
         }
 
-        ret = sysdb_getgrnam(cmdctx, dom, name, &dctx->res);
+        ret = sysdb_getgrnam_with_views(cmdctx, dom, name, &dctx->res);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Failed to make request to our cache!\n");
@@ -2991,10 +3016,15 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
         /* if this is a caching provider (or if we haven't checked the cache
          * yet) then verify that the cache is uptodate */
         if (dctx->check_provider) {
-            ret = check_cache(dctx, nctx, dctx->res,
-                              SSS_DP_GROUP, name, 0, NULL,
-                              nss_cmd_getby_dp_callback,
-                              dctx);
+
+            if (DOM_HAS_VIEWS(dom) && dctx->res->count == 0) {
+                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+            } else {
+                extra_flag = NULL;
+            }
+
+            ret = check_cache(dctx, nctx, dctx->res, SSS_DP_GROUP, name, 0,
+                              extra_flag, nss_cmd_getby_dp_callback, dctx);
             if (ret != EOK) {
                 /* Anything but EOK means we should reenter the mainloop
                  * because we may be refreshing the cache
@@ -3036,6 +3066,7 @@ static int nss_cmd_getgrgid_search(struct nss_dom_ctx *dctx)
     struct nss_ctx *nctx;
     int ret;
     int err;
+    const char *extra_flag = NULL;
 
     nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
 
@@ -3075,7 +3106,7 @@ static int nss_cmd_getgrgid_search(struct nss_dom_ctx *dctx)
             goto done;
         }
 
-        ret = sysdb_getgrgid(cmdctx, dom, cmdctx->id, &dctx->res);
+        ret = sysdb_getgrgid_with_views(cmdctx, dom, cmdctx->id, &dctx->res);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Failed to make request to our cache!\n");
@@ -3106,9 +3137,15 @@ static int nss_cmd_getgrgid_search(struct nss_dom_ctx *dctx)
         /* if this is a caching provider (or if we haven't checked the cache
          * yet) then verify that the cache is uptodate */
         if (dctx->check_provider) {
-            ret = check_cache(dctx, nctx, dctx->res,
-                              SSS_DP_GROUP, NULL, cmdctx->id, NULL,
-                              nss_cmd_getby_dp_callback,
+
+            if (DOM_HAS_VIEWS(dom) && dctx->res->count == 0) {
+                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+            } else {
+                extra_flag = NULL;
+            }
+
+            ret = check_cache(dctx, nctx, dctx->res, SSS_DP_GROUP, NULL,
+                              cmdctx->id, extra_flag, nss_cmd_getby_dp_callback,
                               dctx);
             if (ret != EOK) {
                 /* Anything but EOK means we should reenter the mainloop
-- 
1.8.3.1

-------------- next part --------------
From 70ff7f91665082ae2a9ea82896395cce21c9b67e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 2 Oct 2014 18:10:39 +0200
Subject: [PATCH 12/15] sid2name: return name without views applied

Make sure that the original name of an object without any overrides
applied is returned by sid2name requests.
---
 src/db/sysdb_ops.c             |  1 +
 src/responder/nss/nsssrv_cmd.c | 14 ++++++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 1d51119..c88ff9b 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -3507,6 +3507,7 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
 {
     TALLOC_CTX *tmp_ctx;
     const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM,
+                                ORIGINALAD_PREFIX SYSDB_NAME,
                                 SYSDB_OBJECTCLASS, NULL };
     struct ldb_dn *basedn;
     int ret;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 9e827e6..4b34c01 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -4635,11 +4635,12 @@ static errno_t fill_orig(struct sss_packet *packet,
 static errno_t fill_name(struct sss_packet *packet,
                          struct sss_domain_info *dom,
                          enum sss_id_type id_type,
+                         bool apply_no_view,
                          struct ldb_message *msg)
 {
     int ret;
     TALLOC_CTX *tmp_ctx = NULL;
-    const char *orig_name;
+    const char *orig_name = NULL;
     const char *cased_name;
     const char *fq_name;
     struct sized_string name;
@@ -4648,7 +4649,15 @@ static errno_t fill_name(struct sss_packet *packet,
     size_t blen;
     size_t pctr = 0;
 
-    orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+    if (apply_no_view) {
+        orig_name = ldb_msg_find_attr_as_string(msg,
+                                                ORIGINALAD_PREFIX SYSDB_NAME,
+                                                NULL);
+    }
+
+    if (orig_name == NULL) {
+        orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+    }
     if (orig_name == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Missing name.\n");
         return EINVAL;
@@ -4767,6 +4776,7 @@ static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx)
         ret = fill_name(cctx->creq->out,
                         dctx->domain,
                         id_type,
+                        true,
                         dctx->res->msgs[0]);
         break;
     case SSS_NSS_GETIDBYSID:
-- 
1.8.3.1

-------------- next part --------------
From e9c9bee3a10b0cc22939ca0a0546db5d23292b41 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 15 Oct 2014 12:59:08 +0200
Subject: [PATCH 13/15] pam: make pam responder aware if views

---
 src/responder/pam/pamsrv_cmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index ffec17b..dd0e6e4 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -1123,7 +1123,7 @@ static int pam_check_user_search(struct pam_auth_req *preq)
         if (preq->pd->name_is_upn) {
             ret = sysdb_search_user_by_upn(preq, dom, name, user_attrs, &msg);
         } else {
-            ret = sysdb_getpwnam(preq, dom, name, &res);
+            ret = sysdb_getpwnam_with_views(preq, dom, name, &res);
             if (res->count > 1) {
                 DEBUG(SSSDBG_FATAL_FAILURE,
                       "getpwnam call returned more than one result !?!\n");
-- 
1.8.3.1

-------------- next part --------------
From 3955564a9a5b9e22e6c8be4902a732b530e4ed9b Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 17 Oct 2014 13:52:24 +0200
Subject: [PATCH 14/15] sysdb: add sysdb_enumpw/grent_with_views()

---
 src/db/sysdb.h        |  8 +++++
 src/db/sysdb_search.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index f7e507c..fa5b714 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -543,6 +543,10 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
                     struct sss_domain_info *domain,
                     struct ldb_result **res);
 
+int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
+                               struct sss_domain_info *domain,
+                               struct ldb_result **res);
+
 int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
                    struct sss_domain_info *domain,
                    const char *name,
@@ -557,6 +561,10 @@ int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
                     struct sss_domain_info *domain,
                     struct ldb_result **res);
 
+int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
+                               struct sss_domain_info *domain,
+                               struct ldb_result **res);
+
 struct sysdb_netgroup_ctx {
     enum {SYSDB_NETGROUP_TRIPLE_VAL, SYSDB_NETGROUP_GROUP_VAL} type;
     union {
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 4077dd4..d2b6f0f 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -295,6 +295,46 @@ done:
     return ret;
 }
 
+int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
+                               struct sss_domain_info *domain,
+                               struct ldb_result **_res)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_result *res;
+    size_t c;
+    int ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    ret = sysdb_enumpwent(tmp_ctx, domain, &res);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumpwent failed.\n");
+        goto done;
+    }
+
+    if (DOM_HAS_VIEWS(domain)) {
+        for (c = 0; c < res->count; c++) {
+            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL);
+            /* enumeration assumes that the cache is up-to-date, hence we do not
+             * need to handle ENOENT separately. */
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
+                goto done;
+            }
+        }
+    }
+
+    *_res = talloc_steal(mem_ctx, res);
+
+done:
+    talloc_zfree(tmp_ctx);
+    return ret;
+}
+
 /* groups */
 
 static int mpg_convert(struct ldb_message *msg)
@@ -679,6 +719,54 @@ done:
     return ret;
 }
 
+int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
+                               struct sss_domain_info *domain,
+                               struct ldb_result **_res)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct ldb_result *res;
+    size_t c;
+    int ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    ret = sysdb_enumgrent(tmp_ctx, domain,&res);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumgrent failed.\n");
+        goto done;
+    }
+
+    if (DOM_HAS_VIEWS(domain)) {
+        for (c = 0; c < res->count; c++) {
+            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL);
+            /* enumeration assumes that the cache is up-to-date, hence we do not
+             * need to handle ENOENT separately. */
+            if (ret != EOK) {
+                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;
+            }
+        }
+    }
+
+
+    *_res = talloc_steal(mem_ctx, res);
+
+done:
+    talloc_zfree(tmp_ctx);
+    return ret;
+}
+
 int sysdb_initgroups(TALLOC_CTX *mem_ctx,
                      struct sss_domain_info *domain,
                      const char *name,
-- 
1.8.3.1



More information about the sssd-devel mailing list