Blob Blame History Raw
From 0f907d8501387ec32dbb00e1c38d5da25e698f90 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 14 Nov 2017 13:14:14 +0100
Subject: [PATCH 57/57] sysdb: remove IDXONE and objectClass from users and
 groups
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch does the needed sysdb update for the previous to patches. It
removes the one-level search index IDXONE and replaces objectClass with
objectCategory in the user and group objects.

Related to https://pagure.io/SSSD/sssd/issue/3503

Reviewed-by: Fabiano FidĂȘncio <fidencio@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 2927da49dd8a16fff6312d89ad43cc355655800c)
---
 src/db/sysdb_init.c    |  52 +++++++++++-
 src/db/sysdb_private.h |  11 ++-
 src/db/sysdb_upgrade.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 274 insertions(+), 6 deletions(-)

diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c
index 44a7918f603fe1368b7d81738666de6bb47b83d0..74ad23f3050da0ae14fa495d2302f4a858fcd3c5 100644
--- a/src/db/sysdb_init.c
+++ b/src/db/sysdb_init.c
@@ -359,8 +359,48 @@ static errno_t sysdb_ts_cache_upgrade(TALLOC_CTX *mem_ctx,
                                       const char *cur_version,
                                       const char **_new_version)
 {
-    /* Currently the sysdb cache only has one version */
-    return EFAULT;
+    errno_t ret;
+    TALLOC_CTX *tmp_ctx;
+    const char *version;
+    struct ldb_context *save_ldb;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    /* The upgrade process depends on having ldb around, yet the upgrade
+     * function shouldn't set the ldb pointer, only the connect function
+     * should after it's successful. To avoid hard refactoring, save the
+     * ldb pointer here and restore in the 'done' handler
+     */
+    save_ldb = sysdb->ldb;
+    sysdb->ldb = ldb;
+
+    version = talloc_strdup(tmp_ctx, cur_version);
+    if (version == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    DEBUG(SSSDBG_CONF_SETTINGS,
+          "Upgrading timstamp cache of DB [%s] from version: %s\n",
+          domain->name, version);
+
+    if (strcmp(version, SYSDB_TS_VERSION_0_1) == 0) {
+        ret = sysdb_ts_upgrade_01(sysdb, &version);
+        if (ret != EOK) {
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+    sysdb->ldb = save_ldb;
+    *_new_version = version;
+    talloc_free(tmp_ctx);
+    return ret;
 }
 
 static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx,
@@ -511,6 +551,14 @@ static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx,
         }
     }
 
+    if (strcmp(version, SYSDB_VERSION_0_19) == 0) {
+        ret = sysdb_upgrade_19(sysdb, &version);
+        if (ret != EOK) {
+            goto done;
+        }
+    }
+
+
     ret = EOK;
 done:
     sysdb->ldb = save_ldb;
diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
index dbd75615bc212e73c4338a76dceaa68a5889ed1d..cac06ba46da23080d1ab661502d0792bd37b9291 100644
--- a/src/db/sysdb_private.h
+++ b/src/db/sysdb_private.h
@@ -23,6 +23,7 @@
 #ifndef __INT_SYS_DB_H__
 #define __INT_SYS_DB_H__
 
+#define SYSDB_VERSION_0_20 "0.20"
 #define SYSDB_VERSION_0_19 "0.19"
 #define SYSDB_VERSION_0_18 "0.18"
 #define SYSDB_VERSION_0_17 "0.17"
@@ -43,7 +44,7 @@
 #define SYSDB_VERSION_0_2 "0.2"
 #define SYSDB_VERSION_0_1 "0.1"
 
-#define SYSDB_VERSION SYSDB_VERSION_0_19
+#define SYSDB_VERSION SYSDB_VERSION_0_20
 
 #define SYSDB_BASE_LDIF \
      "dn: @ATTRIBUTES\n" \
@@ -72,7 +73,6 @@
      "@IDXATTR: sudoUser\n" \
      "@IDXATTR: sshKnownHostsExpire\n" \
      "@IDXATTR: objectSIDString\n" \
-     "@IDXONE: 1\n" \
      "@IDXATTR: ghost\n" \
      "@IDXATTR: userPrincipalName\n" \
      "@IDXATTR: canonicalUserPrincipalName\n" \
@@ -92,9 +92,10 @@
      "\n"
 
 /* The timestamp cache has its own versioning */
+#define SYSDB_TS_VERSION_0_2 "0.2"
 #define SYSDB_TS_VERSION_0_1 "0.1"
 
-#define SYSDB_TS_VERSION SYSDB_TS_VERSION_0_1
+#define SYSDB_TS_VERSION SYSDB_TS_VERSION_0_2
 
 #define SYSDB_TS_BASE_LDIF \
      "dn: @ATTRIBUTES\n" \
@@ -103,7 +104,6 @@
      "dn: @INDEXLIST\n" \
      "@IDXATTR: lastUpdate\n" \
      "@IDXATTR: dataExpireTimestamp\n" \
-     "@IDXONE: 1\n" \
      "\n" \
      "dn: cn=sysdb\n" \
      "cn: sysdb\n" \
@@ -169,6 +169,9 @@ int sysdb_upgrade_17(struct sysdb_ctx *sysdb,
                      struct sysdb_dom_upgrade_ctx *upgrade_ctx,
                      const char **ver);
 int sysdb_upgrade_18(struct sysdb_ctx *sysdb, const char **ver);
+int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver);
+
+int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver);
 
 int sysdb_add_string(struct ldb_message *msg,
                      const char *attr, const char *value);
diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
index 365d45f7ebd78523ca9ec4b9c2158cc09acb5489..bc157a24664239bc1255e49a1825243a07acc90f 100644
--- a/src/db/sysdb_upgrade.c
+++ b/src/db/sysdb_upgrade.c
@@ -2317,6 +2317,223 @@ done:
     return ret;
 }
 
+static errno_t add_object_category(struct ldb_context *ldb,
+                                   struct upgrade_ctx *ctx)
+{
+    errno_t ret;
+    struct ldb_result *objects = NULL;
+    const char *attrs[] = { SYSDB_OBJECTCLASS, NULL };
+    struct ldb_dn *base_dn;
+    size_t c;
+    const char *class_name;
+    struct ldb_message *msg = NULL;
+    struct ldb_message *del_msg = NULL;
+
+    base_dn = ldb_dn_new(ctx, ldb, SYSDB_BASE);
+    if (base_dn == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed create base dn.\n");
+        return ENOMEM;
+    }
+
+    ret = ldb_search(ldb, ctx, &objects, base_dn,
+                     LDB_SCOPE_SUBTREE, attrs,
+                     "(|("SYSDB_OBJECTCLASS"="SYSDB_USER_CLASS")"
+                       "("SYSDB_OBJECTCLASS"="SYSDB_GROUP_CLASS"))");
+    talloc_free(base_dn);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to search objects: %d\n", ret);
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    if (objects == NULL || objects->count == 0) {
+        DEBUG(SSSDBG_TRACE_LIBS, "No objects found, nothing to do.");
+        ret = EOK;
+        goto done;
+    }
+
+    del_msg = ldb_msg_new(ctx);
+    if (del_msg == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+    ret = ldb_msg_add_empty(del_msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_DELETE,
+                            NULL);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_ALL, "Found [%d] objects.\n", objects->count);
+    for (c = 0; c < objects->count; c++) {
+        DEBUG(SSSDBG_TRACE_ALL, "Updating [%s].\n",
+              ldb_dn_get_linearized(objects->msgs[c]->dn));
+
+        class_name = ldb_msg_find_attr_as_string(objects->msgs[c],
+                                                 SYSDB_OBJECTCLASS, NULL);
+        if (class_name == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "Searched objects by objectClass, "
+                                     "but result does not have one.\n");
+            ret = EINVAL;
+            goto done;
+        }
+
+        talloc_free(msg);
+        msg = ldb_msg_new(ctx);
+        if (msg == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        msg->dn = objects->msgs[c]->dn;
+        del_msg->dn = objects->msgs[c]->dn;
+
+        ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCATEGORY, LDB_FLAG_MOD_ADD,
+                                NULL);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        ret = ldb_msg_add_string(msg, SYSDB_OBJECTCATEGORY, class_name);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        DEBUG(SSSDBG_TRACE_ALL, "Adding [%s] to [%s].\n", class_name,
+              ldb_dn_get_linearized(objects->msgs[c]->dn));
+        ret = ldb_modify(ldb, msg);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "Failed to add objectCategory to %s: %d.\n",
+                  ldb_dn_get_linearized(objects->msgs[c]->dn),
+                  sysdb_error_to_errno(ret));
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        ret = ldb_modify(ldb, del_msg);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "Failed to remove objectClass from %s: %d.\n",
+                  ldb_dn_get_linearized(objects->msgs[c]->dn),
+                  sysdb_error_to_errno(ret));
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(msg);
+    talloc_free(del_msg);
+    talloc_free(objects);
+
+    return ret;
+}
+
+int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver)
+{
+    struct upgrade_ctx *ctx;
+    errno_t ret;
+    struct ldb_message *msg = NULL;
+
+    ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_20, &ctx);
+    if (ret) {
+        return ret;
+    }
+
+    ret = add_object_category(sysdb->ldb, ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "add_object_category failed.\n");
+        goto done;
+    }
+
+    /* Remove @IDXONE from index */
+    msg = ldb_msg_new(ctx);
+    if (msg == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST");
+    if (msg->dn == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_msg_add_empty(msg, "@IDXONE", LDB_FLAG_MOD_DELETE, NULL);
+    if (ret != LDB_SUCCESS) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_modify(sysdb->ldb, msg);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    /* conversion done, update version number */
+    ret = update_version(ctx);
+
+done:
+    ret = finish_upgrade(ret, &ctx, ver);
+    return ret;
+}
+
+int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver)
+{
+    struct upgrade_ctx *ctx;
+    errno_t ret;
+    struct ldb_message *msg = NULL;
+
+    ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_TS_VERSION_0_2, &ctx);
+    if (ret) {
+        return ret;
+    }
+
+    /* Remove @IDXONE from index */
+    talloc_free(msg);
+    msg = ldb_msg_new(ctx);
+    if (msg == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST");
+    if (msg->dn == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_msg_add_empty(msg, "@IDXONE", LDB_FLAG_MOD_DELETE, NULL);
+    if (ret != LDB_SUCCESS) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_modify(sysdb->ldb, msg);
+    if (ret != LDB_SUCCESS) {
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    /* conversion done, update version number */
+    ret = update_version(ctx);
+
+done:
+    ret = finish_upgrade(ret, &ctx, ver);
+    return ret;
+}
+
 /*
  * Example template for future upgrades.
  * Copy and change version numbers as appropriate.
-- 
2.14.3