From d986fc2fa4e2592ea4097a0192e335970053be99 Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Mon, 23 Apr 2012 04:49:16 -0400
Subject: [PATCH 04/10] Ghost members - modifications in sysdb

Deleted sysdb_add_fake_user():
This function is no longer used.

Modified sysdb_add_user():
When user object is added to sysdb, it is important to iterate over all
groups that might have its name or any of its aliases as ghost member
and replace this ghost membership by a real one. This will eliminate
duplicite memberships.
---
 src/db/sysdb.h     |    5 --
 src/db/sysdb_ops.c |  178 +++++++++++++++++++++++++++++++---------------------
 2 files changed, 107 insertions(+), 76 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 9e7d3c5ca2b584ac306891cbec34d63132649e0f..85dde2c4908b9c502921a82558ff09329c4052ca 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -583,11 +583,6 @@ int sysdb_add_user(struct sysdb_ctx *sysdb,
                    int cache_timeout,
                    time_t now);
 
-int sysdb_add_fake_user(struct sysdb_ctx *sysdb,
-                        const char *name,
-                        const char *original_dn,
-                        time_t now);
-
 /* Add group (only basic attrs and w/o checks) */
 int sysdb_add_basic_group(struct sysdb_ctx *sysdb,
                           const char *name, gid_t gid);
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 59b3bcaeb0300fcc130d6d5c9c8d24960f1798f1..dd4fda2f0b6ce16b316d71b60062be8e7f1f35e7 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -860,9 +860,16 @@ int sysdb_add_user(struct sysdb_ctx *sysdb,
 {
     TALLOC_CTX *tmp_ctx;
     struct ldb_message *msg;
+    struct ldb_message **groups;
+    struct ldb_message_element *alias_el;
+    size_t group_count = 0;
     struct sysdb_attrs *id_attrs;
+    const char *group_attrs[] = {SYSDB_NAME, SYSDB_GHOST, NULL};
+    struct ldb_dn *tmpdn;
+    const char *userdn;
+    char *filter;
     uint32_t id;
-    int ret;
+    int ret, i, j;
 
     struct sss_domain_info *domain = sysdb->domain;
 
@@ -971,6 +978,105 @@ int sysdb_add_user(struct sysdb_ctx *sysdb,
 
     ret = sysdb_set_user_attr(sysdb, name, attrs, SYSDB_MOD_REP);
 
+    /* remove all ghost users */
+    filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", SYSDB_GHOST, name);
+    if (!filter) {
+        ret = ENOMEM;
+        goto done;
+    }
+    ret = sysdb_attrs_get_el(attrs, SYSDB_NAME_ALIAS, &alias_el);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    for (i = 0; i < alias_el->num_values; i++) {
+        filter = talloc_asprintf_append(filter, "(%s=%s)",
+                                        SYSDB_GHOST, alias_el->values[i].data);
+        if (filter == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    filter = talloc_asprintf_append(filter, ")");
+    if (filter == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    tmpdn = sysdb_user_dn(sysdb, tmp_ctx, sysdb->domain->name, name);
+    if (!tmpdn) {
+        ERROR_OUT(ret, ENOMEM, done);
+    }
+
+    userdn = ldb_dn_get_linearized(tmpdn);
+    if (!userdn) {
+        ERROR_OUT(ret, EINVAL, done);
+    }
+
+    tmpdn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
+                            SYSDB_TMPL_GROUP_BASE, sysdb->domain->name);
+    if (!tmpdn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    /* We need to find all groups that contain this object as a ghost user
+     * and replace the ghost user there by actual member record
+     * Note that this object can be referred to either by its name or any
+     * of its aliases
+     */
+    ret = sysdb_search_entry(tmp_ctx, sysdb, tmpdn, LDB_SCOPE_SUBTREE, filter,
+                             group_attrs, &group_count, &groups);
+    if (ret != EOK && ret != ENOENT) {
+        goto done;
+    }
+
+    for (i = 0; i < group_count; i++) {
+        msg = ldb_msg_new(tmp_ctx);
+        if (!msg) {
+            ERROR_OUT(ret, ENOMEM, done);
+        }
+
+        msg->dn = groups[i]->dn;
+        ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, SYSDB_MOD_ADD, NULL);
+        if (ret != LDB_SUCCESS) {
+            ERROR_OUT(ret, ENOMEM, done);
+        }
+
+        ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", userdn);
+        if (ret != LDB_SUCCESS) {
+            ERROR_OUT(ret, EINVAL, done);
+        }
+
+        ret = ldb_msg_add_empty(msg, SYSDB_GHOST, SYSDB_MOD_DEL, NULL);
+        if (ret != LDB_SUCCESS) {
+            ERROR_OUT(ret, ENOMEM, done);
+        }
+        ret = ldb_msg_add_fmt(msg, SYSDB_GHOST, "%s", name);
+        if (ret != LDB_SUCCESS) {
+            ERROR_OUT(ret, EINVAL, done);
+        }
+        /* Delete aliases from the ghost attribute as well */
+        for (j = 0; j < alias_el->num_values; j++) {
+            ret = ldb_msg_add_fmt(msg, SYSDB_GHOST, "%s",
+                                  (char *)alias_el->values[j].data);
+            if (ret != LDB_SUCCESS) {
+                ERROR_OUT(ret, EINVAL, done);
+            }
+        }
+
+        ret = ldb_modify(sysdb->ldb, msg);
+        ret = sysdb_error_to_errno(ret);
+        if (ret != EOK) {
+            goto done;
+        }
+
+        talloc_zfree(msg);
+    }
+
+    ret = EOK;
+
 done:
     if (ret == EOK) {
         ret = ldb_transaction_commit(sysdb->ldb);
@@ -983,76 +1089,6 @@ done:
     return ret;
 }
 
-int sysdb_add_fake_user(struct sysdb_ctx *sysdb,
-                        const char *name,
-                        const char *original_dn,
-                        time_t now)
-{
-    TALLOC_CTX *tmp_ctx;
-    struct ldb_message *msg;
-    int ret;
-
-    tmp_ctx = talloc_new(NULL);
-    if (!tmp_ctx) {
-        return ENOMEM;
-    }
-
-    msg = ldb_msg_new(tmp_ctx);
-    if (!msg) {
-        ERROR_OUT(ret, ENOMEM, done);
-    }
-
-    /* user dn */
-    msg->dn = sysdb_user_dn(sysdb, msg, sysdb->domain->name, name);
-    if (!msg->dn) {
-        ERROR_OUT(ret, ENOMEM, done);
-    }
-
-    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS);
-    if (ret) goto done;
-
-    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
-    if (ret) goto done;
-
-    if (!now) {
-        now = time(NULL);
-    }
-
-    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
-                    (unsigned long) now);
-    if (ret) goto done;
-
-    /* set last login so that the fake entry does not get cleaned up
-     * immediately */
-    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_LAST_LOGIN,
-                    (unsigned long) now);
-    if (ret) return ret;
-
-    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_LAST_UPDATE,
-                    (unsigned long) now);
-    if (ret) goto done;
-
-    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CACHE_EXPIRE,
-                    (unsigned long) now-1);
-    if (ret) goto done;
-
-    if (original_dn) {
-        ret = add_string(msg, LDB_FLAG_MOD_ADD,
-                         SYSDB_ORIG_DN, original_dn);
-        if (ret) goto done;
-    }
-
-    ret = ldb_add(sysdb->ldb, msg);
-    ret = sysdb_error_to_errno(ret);
-
-done:
-    if (ret != EOK) {
-        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
-    }
-    talloc_zfree(tmp_ctx);
-    return ret;
-}
-
 /* =Add-Basic-Group-NO-CHECKS============================================= */
 
 int sysdb_add_basic_group(struct sysdb_ctx *sysdb,
-- 
1.7.7.6

