From 5eb3cfcb3a48ec476a87e8b5f98378c166156bc5 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/4] Add sysdb_get_user_attr_with_views

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

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 04733f2a82fd60708403e8be4e66991f5d735c20..0d0971d98dd684e47ae8ec067447169f41ebba67 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -612,6 +612,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 ca52f1185786b9e10d4e08bd76a39a218746d3bc..bbc5af8a02777c1519a9d0b5d77c50559e66f462 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -1028,6 +1028,118 @@ 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;
+    }
+
+    /* Assume that overrideDN is requested to simplify the code. If no view
+     * is applied it doesn't really matter. */
+    has_override_dn = true;
+    attrs = attributes;
+
+    /* If there are views we first have to search the overrides for matches */
+    if (DOM_HAS_VIEWS(domain)) {
+        /* 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) {
+            /* 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;
+        }
+
+        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

