From 693a2c4392424e95acef1e38647fc5cf67f50f71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 2 Oct 2014 16:13:53 +0200
Subject: [PATCH 2/5] Add sysdb_get_user_attr_with_views

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

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 1f21f151d860eafc56c0970b23bbed25b239b157..8a32ab2e9d735404956869699e1576b031af8090 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -593,6 +593,12 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
                         const char **attributes,
                         struct ldb_result **res);
 
+int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
+                                   struct sss_domain_info *domain,
+                                   const char *name,
+                                   const char **attributes,
+                                   struct ldb_result **res);
+
 int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx,
                             struct sss_domain_info *domain,
                             const char *netgrname,
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index b5033a47af6ee8bb5c92ea556fcf2de301bac63d..01517b5b0091bd6066b869b76cebb363fae73604 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -948,6 +948,116 @@ done:
     return ret;
 }
 
+int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
+                                   struct sss_domain_info *domain,
+                                   const char *name,
+                                   const char **attributes,
+                                   struct ldb_result **_res)
+{
+    int ret;
+    struct ldb_result *orig_obj = NULL;
+    struct ldb_result *override_obj = NULL;
+    struct ldb_message_element *el = NULL;
+    const char **attrs = NULL;
+    bool has_override_dn;
+    TALLOC_CTX *tmp_ctx;
+    int count;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    /* We need overrideDN for views, so append it if missing. */
+    has_override_dn = false;
+    for (count = 0; attributes[count] != NULL; count++) {
+        if (strcmp(attributes[count], SYSDB_OVERRIDE_DN) == 0) {
+            has_override_dn = true;
+            break;
+        }
+    }
+
+    if (has_override_dn) {
+        /* Use original attributes. */
+        attrs = attributes;
+    } else {
+        /* Copy original attributes and add overrideDN. */
+        attrs = talloc_zero_array(tmp_ctx, const char *, count + 2);
+        if (attrs == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        for (count = 0; attributes[count] != NULL; count++) {
+            attrs[count] = attributes[count];
+        }
+
+        attrs[count] = SYSDB_OVERRIDE_DN;
+    }
+
+    /* If there are views we first have to search the overrides for matches */
+    if (DOM_HAS_VIEWS(domain)) {
+        ret = sysdb_search_user_override_attrs_by_name(tmp_ctx, domain, name,
+                                            attrs, &override_obj, &orig_obj);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "sysdb_search_user_override_attrs_by_name failed.\n");
+            return ret;
+        }
+    }
+
+    /* If there are no views or nothing was found in the overrides the
+     * original objects are searched. */
+    if (orig_obj == NULL) {
+        ret = sysdb_get_user_attr(tmp_ctx, domain, name, attrs, &orig_obj);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_user_attr failed.\n");
+            return ret;
+        }
+    }
+
+    /* 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");
+            return ret;
+        }
+
+        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;
+        }
+    }
+
+    /* Remove overrideDN if needed. */
+    if (!has_override_dn && orig_obj != NULL && orig_obj->count == 1) {
+        el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_OVERRIDE_DN);
+        if (el == NULL) {
+            ret = EINVAL;
+            goto done;
+        }
+
+        ldb_msg_remove_element(orig_obj->msgs[0], el);
+    }
+
+    *_res = talloc_steal(mem_ctx, orig_obj);
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 /* This function splits a three-tuple into three strings
  * It assumes that any whitespace between the parentheses
  * and commas are intentional and does not attempt to
-- 
1.7.11.7

