URL: https://github.com/SSSD/sssd/pull/450
Author: sumit-bose
 Title: #450: sysdb: do not use objectClass for users and groups
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/450/head:pr450
git checkout pr450
From 8bd4ec34c755534fac705d1d96cf7e8c68dfaad9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Wed, 8 Nov 2017 14:04:40 +0100
Subject: [PATCH 1/4] sysdb: be_refresh_get_values_ex() remove unused option

The objectclass argument is not used in be_refresh_get_values_ex()
anymore.

Related to https://pagure.io/SSSD/sssd/issue/3503
---
 src/providers/be_refresh.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/src/providers/be_refresh.c b/src/providers/be_refresh.c
index 81f2c5d1d..e8cf5da75 100644
--- a/src/providers/be_refresh.c
+++ b/src/providers/be_refresh.c
@@ -32,7 +32,6 @@
 static errno_t be_refresh_get_values_ex(TALLOC_CTX *mem_ctx,
                                         struct sss_domain_info *domain,
                                         time_t period,
-                                        const char *objectclass,
                                         struct ldb_dn *base_dn,
                                         const char *attr,
                                         char ***_values)
@@ -96,21 +95,17 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
                                      char ***_values)
 {
     struct ldb_dn *base_dn = NULL;
-    const char *class = NULL;
     errno_t ret;
 
     switch (type) {
     case BE_REFRESH_TYPE_USERS:
         base_dn = sysdb_user_base_dn(mem_ctx, domain);
-        class = SYSDB_USER_CLASS;
         break;
     case BE_REFRESH_TYPE_GROUPS:
         base_dn = sysdb_group_base_dn(mem_ctx, domain);
-        class = SYSDB_GROUP_CLASS;
         break;
     case BE_REFRESH_TYPE_NETGROUPS:
         base_dn = sysdb_netgroup_base_dn(mem_ctx, domain);
-        class = SYSDB_NETGROUP_CLASS;
         break;
     case BE_REFRESH_TYPE_SENTINEL:
         return ERR_INTERNAL;
@@ -121,7 +116,7 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
         return ENOMEM;
     }
 
-    ret = be_refresh_get_values_ex(mem_ctx, domain, period, class,
+    ret = be_refresh_get_values_ex(mem_ctx, domain, period,
                                    base_dn, SYSDB_NAME, _values);
 
     talloc_free(base_dn);

From 0c5f9be30dff567c7ebbe4787e66ae41266839a0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Wed, 8 Nov 2017 15:14:58 +0100
Subject: [PATCH 2/4] sysdb: do not use objectClass for users and groups

The majority of the object in the SSSD cache are users and groups. If
there are many user and groups in the cache the index objects of the
objectclass attributes 'user' and 'group' become  large because the
must hold references to all objects of those object classes.

As a result the management of these index objects becomes costly because
they must be parsed and split apart quite often. Additionally they are
mostly useless because user and groups are lookup up by more specific
attributes in general.

Only when enumerating all user or groups this kind of index might be
useful.

There are two way of removing this kind of index from the user and group
objects. Either by removing objectClass from the list of indexes and add
a new attribute to all other type of object we want and index for. Or by
replacing objectClass with a different attribute for the user and group
objects. After some testing I think the latter one is the more reliable
one and implemented it in this patch.

Related to https://pagure.io/SSSD/sssd/issue/3503
---
 src/db/sysdb.h                                     | 10 ++--
 src/db/sysdb_init.c                                |  5 +-
 src/db/sysdb_ops.c                                 |  6 +--
 src/db/sysdb_search.c                              | 11 +++--
 src/db/sysdb_upgrade.c                             |  4 ++
 src/ldb_modules/memberof.c                         |  6 +--
 src/providers/ipa/ipa_id.c                         |  7 +--
 src/providers/ipa/ipa_subdomains_id.c              |  2 +-
 src/providers/krb5/krb5_renew_tgt.c                |  3 +-
 src/providers/ldap/ldap_id_cleanup.c               |  2 +-
 src/providers/ldap/sdap_async_groups.c             |  6 +--
 src/providers/ldap/sdap_async_initgroups_ad.c      |  2 +-
 src/providers/ldap/sdap_async_nested_groups.c      |  2 +-
 .../common/cache_req/plugins/cache_req_common.c    |  2 +-
 src/responder/ifp/ifp_cache.c                      |  4 +-
 src/responder/ifp/ifp_groups.c                     |  2 +-
 src/responder/ifp/ifp_users.c                      |  2 +-
 src/responder/nss/nss_protocol_grent.c             |  2 +-
 src/responder/nss/nss_protocol_sid.c               |  4 +-
 src/tests/cmocka/test_ad_common.c                  |  2 +-
 src/tests/cmocka/test_ipa_subdomains_server.c      | 54 ++++++++++++++++------
 src/tests/sysdb-tests.c                            | 20 +++++---
 src/tools/sssctl/sssctl_cache.c                    |  3 +-
 23 files changed, 103 insertions(+), 58 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 4192f9085..fd18ecefe 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -192,9 +192,10 @@
 
 #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)"
 
-#define SYSDB_UC "objectclass="SYSDB_USER_CLASS
-#define SYSDB_GC "objectclass="SYSDB_GROUP_CLASS
-#define SYSDB_NC "objectclass="SYSDB_NETGROUP_CLASS
+#define SYSDB_OBJECTCATEGORY "objectCategory"
+#define SYSDB_UC SYSDB_OBJECTCATEGORY"="SYSDB_USER_CLASS
+#define SYSDB_GC SYSDB_OBJECTCATEGORY"="SYSDB_GROUP_CLASS
+#define SYSDB_NC SYSDB_OBJECTCLASS"="SYSDB_NETGROUP_CLASS
 #define SYSDB_MPGC "|("SYSDB_UC")("SYSDB_GC")"
 
 #define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))"
@@ -227,7 +228,8 @@
 #define SYSDB_DEFAULT_ATTRS SYSDB_LAST_UPDATE, \
                             SYSDB_CACHE_EXPIRE, \
                             SYSDB_INITGR_EXPIRE, \
-                            SYSDB_OBJECTCLASS
+                            SYSDB_OBJECTCLASS, \
+                            SYSDB_OBJECTCATEGORY
 
 #define SYSDB_PW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
                         SYSDB_GIDNUM, SYSDB_GECOS, \
diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c
index e246a165e..44a7918f6 100644
--- a/src/db/sysdb_init.c
+++ b/src/db/sysdb_init.c
@@ -31,11 +31,12 @@
 #define LDB_MODULES_PATH "LDB_MODULES_PATH"
 
 /* If an entry differs only in these attributes, they are written to
- * the timestamp cache only. In addition, objectclass is added so that
- * we can distinguish between users and groups.
+ * the timestamp cache only. In addition, objectclass/objectcategory is added
+ * so that we can distinguish between users and groups.
  */
 const char *sysdb_ts_cache_attrs[] = {
     SYSDB_OBJECTCLASS,
+    SYSDB_OBJECTCATEGORY,
     SYSDB_LAST_UPDATE,
     SYSDB_CACHE_EXPIRE,
     SYSDB_ORIG_MODSTAMP,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 1539c41c9..024683317 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -958,7 +958,7 @@ static struct sysdb_attrs *ts_obj_attrs(TALLOC_CTX *mem_ctx,
         return NULL;
     }
 
-    ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, oc);
+    ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCATEGORY, oc);
     if (ret != EOK) {
         talloc_free(attrs);
         return NULL;
@@ -1667,7 +1667,7 @@ int sysdb_add_basic_user(struct sss_domain_info *domain,
         ERROR_OUT(ret, ENOMEM, done);
     }
 
-    ret = sysdb_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS);
+    ret = sysdb_add_string(msg, SYSDB_OBJECTCATEGORY, SYSDB_USER_CLASS);
     if (ret) goto done;
 
     ret = sysdb_add_string(msg, SYSDB_NAME, name);
@@ -2120,7 +2120,7 @@ int sysdb_add_basic_group(struct sss_domain_info *domain,
         ERROR_OUT(ret, ENOMEM, done);
     }
 
-    ret = sysdb_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS);
+    ret = sysdb_add_string(msg, SYSDB_OBJECTCATEGORY, SYSDB_GROUP_CLASS);
     if (ret) goto done;
 
     ret = sysdb_add_string(msg, SYSDB_NAME, name);
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index 808396690..a6a81e23d 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -114,10 +114,11 @@ static errno_t merge_msg_ts_attrs(struct sysdb_ctx *sysdb,
         return EIO;
     }
 
-    /* Deliberately start from 1 in order to not merge objectclass and avoid
-     * breaking MPGs where the OC might be made up
+    /* Deliberately start from 2 in order to not merge
+     * objectclass/objectcategory and avoid breaking MPGs where the OC might
+     * be made up
      */
-    for (size_t c = 1; sysdb_ts_cache_attrs[c]; c++) {
+    for (size_t c = 2; sysdb_ts_cache_attrs[c]; c++) {
         ret = merge_ts_attr(ts_msgs[0], sysdb_msg,
                             sysdb_ts_cache_attrs[c], attrs);
         if (ret != EOK) {
@@ -751,7 +752,7 @@ static int mpg_convert(struct ldb_message *msg)
     struct ldb_val *val = NULL;
     int i;
 
-    el = ldb_msg_find_element(msg, "objectClass");
+    el = ldb_msg_find_element(msg, SYSDB_OBJECTCATEGORY);
     if (!el) return EINVAL;
 
     /* see if this is a user to convert to a group */
@@ -2088,7 +2089,7 @@ errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
     }
 
     member_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(%s=%s))",
-                                    SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS,
+                                    SYSDB_OBJECTCATEGORY, SYSDB_GROUP_CLASS,
                                     SYSDB_MEMBER, sanitized_dn);
     if (!member_filter) {
         ret = ENOMEM;
diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
index 040c91ca6..365d45f7e 100644
--- a/src/db/sysdb_upgrade.c
+++ b/src/db/sysdb_upgrade.c
@@ -149,6 +149,7 @@ int sysdb_upgrade_01(struct ldb_context *ldb, const char **ver)
     struct ldb_dn *mem_dn;
     struct ldb_message *msg;
     const struct ldb_val *val;
+    /* No change needed because this version has objectclass group */
     const char *filter = "(&(memberUid=*)(objectclass=group))";
     const char *attrs[] = { "memberUid", NULL };
     const char *mdn;
@@ -1041,6 +1042,7 @@ int sysdb_upgrade_10(struct sysdb_ctx *sysdb, struct sss_domain_info *domain,
     struct ldb_message_element *memberof_el;
     const char *name;
     struct ldb_dn *basedn;
+    /* No change needed because version 10 has objectclass user */
     const char *filter = "(&(objectClass=user)(!(uidNumber=*))(memberOf=*))";
     const char *attrs[] = { "name", "memberof", NULL };
     struct upgrade_ctx *ctx;
@@ -2082,6 +2084,7 @@ static void qualify_users(struct upgrade_ctx *ctx,
                           struct sss_names_ctx *names,
                           struct ldb_dn *base_dn)
 {
+    /* No change needed because this version has objectclass user */
     const char *user_filter = "objectclass=user";
     const char *user_name_attrs[] = { SYSDB_NAME,
                                       SYSDB_NAME_ALIAS,
@@ -2107,6 +2110,7 @@ static void qualify_groups(struct upgrade_ctx *ctx,
                            struct sss_names_ctx *names,
                            struct ldb_dn *base_dn)
 {
+    /* No change needed because this version has objectclass group */
     const char *group_filter = "objectclass=group";
     const char *group_name_attrs[] = { SYSDB_NAME,
                                        SYSDB_NAME_ALIAS,
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index af7147ee7..327a38c5f 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -31,7 +31,7 @@
 #define DB_USER_CLASS "user"
 #define DB_GROUP_CLASS "group"
 #define DB_CACHE_EXPIRE "dataExpireTimestamp"
-#define DB_OC "objectClass"
+#define DB_OC "objectCategory"
 
 #ifndef MAX
 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
@@ -3928,7 +3928,7 @@ static int memberof_recompute_task(struct ldb_module *module,
 {
     struct ldb_context *ldb = ldb_module_get_ctx(module);
     static const char *attrs[] = { DB_NAME, DB_MEMBEROF, NULL };
-    static const char *filter = "(objectclass=user)";
+    static const char *filter = "("DB_OC"="DB_USER_CLASS")";
     struct mbof_rcmp_context *ctx;
     struct ldb_request *src_req;
     int ret;
@@ -4035,7 +4035,7 @@ static int mbof_rcmp_search_groups(struct mbof_rcmp_context *ctx)
     struct ldb_context *ldb = ldb_module_get_ctx(ctx->module);
     static const char *attrs[] = { DB_MEMBEROF, DB_MEMBERUID,
                                    DB_NAME, DB_MEMBER, NULL };
-    static const char *filter = "(objectclass=group)";
+    static const char *filter = "("DB_OC"="DB_GROUP_CLASS")";
     struct ldb_request *req;
     int ret;
 
diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
index 5044577f0..3896dc3c7 100644
--- a/src/providers/ipa/ipa_id.c
+++ b/src/providers/ipa/ipa_id.c
@@ -431,7 +431,8 @@ static errno_t ipa_id_get_group_uuids(TALLOC_CTX *mem_ctx,
     }
 
     filter = talloc_asprintf(tmp_ctx,
-                             "(&(objectclass=%s)(!(%s=*))(%s=*))",
+                             "(&(%s=%s)(!(%s=*))(%s=*))",
+                             SYSDB_OBJECTCATEGORY,
                              SYSDB_GROUP_CLASS, SYSDB_OVERRIDE_DN,
                              SYSDB_UUID);
     if (filter == NULL) {
@@ -819,7 +820,7 @@ static int ipa_id_get_account_info_post_proc_step(struct tevent_req *req)
     struct ipa_id_get_account_info_state *state = tevent_req_data(req,
                                           struct ipa_id_get_account_info_state);
 
-    class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
+    class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCATEGORY,
                                         NULL);
     if (class == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
@@ -957,7 +958,7 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
         goto fail;
     }
 
-    class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
+    class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCATEGORY,
                                         NULL);
     if (class == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 3530af94e..2ba9813a4 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -888,7 +888,7 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
     struct ldb_message_element *msg_el = NULL;
     size_t c;
 
-    msg_el = ldb_msg_find_element(msg, SYSDB_OBJECTCLASS);
+    msg_el = ldb_msg_find_element(msg, SYSDB_OBJECTCATEGORY);
     if (msg_el == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_find_element failed.\n");
         ret = ENOENT;
diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
index ea6b39deb..549c08c6f 100644
--- a/src/providers/krb5/krb5_renew_tgt.c
+++ b/src/providers/krb5/krb5_renew_tgt.c
@@ -385,8 +385,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx)
 {
     TALLOC_CTX *tmp_ctx;
     int ret;
-    const char *ccache_filter = "(&("SYSDB_CCACHE_FILE"=*)" \
-                                  "("SYSDB_OBJECTCLASS"="SYSDB_USER_CLASS"))";
+    const char *ccache_filter = "(&("SYSDB_CCACHE_FILE"=*)("SYSDB_UC"))";
     const char *ccache_attrs[] = { SYSDB_CCACHE_FILE, SYSDB_UPN, SYSDB_NAME,
                                    SYSDB_CANONICAL_UPN, NULL };
     size_t msgs_count = 0;
diff --git a/src/providers/ldap/ldap_id_cleanup.c b/src/providers/ldap/ldap_id_cleanup.c
index c85ce4591..8c0f0c18b 100644
--- a/src/providers/ldap/ldap_id_cleanup.c
+++ b/src/providers/ldap/ldap_id_cleanup.c
@@ -438,7 +438,7 @@ static int cleanup_groups(TALLOC_CTX *memctx,
              */
             gid = (gid_t) ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
             subfilter = talloc_asprintf(tmpctx, "(&(%s=%s)(|(%s=%s)(%s=%lu)))",
-                                        SYSDB_OBJECTCLASS, SYSDB_USER_CLASS,
+                                        SYSDB_OBJECTCATEGORY, SYSDB_USER_CLASS,
                                         SYSDB_MEMBEROF, sanitized_dn,
                                         SYSDB_GIDNUM, (long unsigned) gid);
         } else {
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index 536e3f137..f084469e7 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -39,7 +39,7 @@ static int sdap_find_entry_by_origDN(TALLOC_CTX *memctx,
                                      bool *_is_group)
 {
     TALLOC_CTX *tmpctx;
-    const char *attrs[] = {SYSDB_OBJECTCLASS,  NULL};
+    const char *attrs[] = {SYSDB_OBJECTCLASS, SYSDB_OBJECTCATEGORY, NULL};
     struct ldb_dn *base_dn;
     char *filter;
     struct ldb_message **msgs;
@@ -90,10 +90,10 @@ static int sdap_find_entry_by_origDN(TALLOC_CTX *memctx,
     }
 
     if (_is_group != NULL) {
-        objectclass = ldb_msg_find_attr_as_string(msgs[0], SYSDB_OBJECTCLASS,
+        objectclass = ldb_msg_find_attr_as_string(msgs[0], SYSDB_OBJECTCATEGORY,
                                                   NULL);
         if (objectclass == NULL) {
-            DEBUG(SSSDBG_OP_FAILURE, "An antry without a %s?\n",
+            DEBUG(SSSDBG_OP_FAILURE, "An entry without a %s?\n",
                   SYSDB_OBJECTCLASS);
             ret = EINVAL;
             goto done;
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
index 2831be977..61aa69a2d 100644
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
@@ -1606,7 +1606,7 @@ sdap_ad_get_domain_local_groups_parse_parents(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = sysdb_attrs_get_string(gr->group, SYSDB_OBJECTCLASS, &class);
+    ret = sysdb_attrs_get_string(gr->group, SYSDB_OBJECTCATEGORY, &class);
     if (ret != EOK) {
         /* If objectclass is missing gr->group is a nested parent found during
          * the nested group lookup. It might not already stored in the cache.
diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c
index 9271d8cfe..b1f9753d7 100644
--- a/src/providers/ldap/sdap_async_nested_groups.c
+++ b/src/providers/ldap/sdap_async_nested_groups.c
@@ -1686,7 +1686,7 @@ static errno_t sdap_nested_group_get_ipa_user(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = sysdb_attrs_add_string(user, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS);
+    ret = sysdb_attrs_add_string(user, SYSDB_OBJECTCATEGORY, SYSDB_USER_CLASS);
     if (ret != EOK) {
         goto done;
     }
diff --git a/src/responder/common/cache_req/plugins/cache_req_common.c b/src/responder/common/cache_req/plugins/cache_req_common.c
index b80f310fe..1f86258bc 100644
--- a/src/responder/common/cache_req/plugins/cache_req_common.c
+++ b/src/responder/common/cache_req/plugins/cache_req_common.c
@@ -53,7 +53,7 @@ cache_req_well_known_sid_msg(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ldberr = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS);
+    ldberr = ldb_msg_add_string(msg, SYSDB_OBJECTCATEGORY, SYSDB_GROUP_CLASS);
     if (ldberr != LDB_SUCCESS) {
         goto done;
     }
diff --git a/src/responder/ifp/ifp_cache.c b/src/responder/ifp/ifp_cache.c
index 8ea2d8008..f84cb14de 100644
--- a/src/responder/ifp/ifp_cache.c
+++ b/src/responder/ifp/ifp_cache.c
@@ -100,7 +100,7 @@ ifp_cache_get_cached_objects(TALLOC_CTX *mem_ctx,
     errno_t ret;
     int ldb_ret;
     int i;
-    const char *attrs[] = {SYSDB_OBJECTCLASS, SYSDB_UIDNUM,
+    const char *attrs[] = {SYSDB_OBJECTCATEGORY, SYSDB_UIDNUM,
                            SYSDB_GIDNUM, NULL};
 
     tmp_ctx = talloc_new(NULL);
@@ -117,7 +117,7 @@ ifp_cache_get_cached_objects(TALLOC_CTX *mem_ctx,
 
     ldb_ret = ldb_search(sysdb_ctx_get_ldb(domain->sysdb), tmp_ctx, &result,
                          base_dn, LDB_SCOPE_SUBTREE, attrs,
-                         "(&(objectClass=%s)(%s=TRUE))", class,
+                         "(&(%s=%s)(%s=TRUE))", SYSDB_OBJECTCATEGORY, class,
                          SYSDB_IFP_CACHED);
     if (ldb_ret != LDB_SUCCESS) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to search the cache\n");
diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c
index 750325423..8ddbf2d49 100644
--- a/src/responder/ifp/ifp_groups.c
+++ b/src/responder/ifp/ifp_groups.c
@@ -888,7 +888,7 @@ ifp_groups_group_get_members(TALLOC_CTX *mem_ctx,
     num_users = 0;
     num_groups = 0;
     for (i = 0; i < num_members; i++) {
-        class = ldb_msg_find_attr_as_string(members[i], SYSDB_OBJECTCLASS,
+        class = ldb_msg_find_attr_as_string(members[i], SYSDB_OBJECTCATEGORY,
                                             NULL);
         if (class == NULL) {
             ret = ERR_INTERNAL;
diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
index 86a1f43a2..cb342a245 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -1441,7 +1441,7 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req,
     }
 
     filter = talloc_asprintf(sbus_req, "(&(%s=%s)(%s=%s))",
-                             SYSDB_OBJECTCLASS, SYSDB_USER_CLASS,
+                             SYSDB_OBJECTCATEGORY, SYSDB_USER_CLASS,
                              SYSDB_NAME, name);
     if (filter == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
diff --git a/src/responder/nss/nss_protocol_grent.c b/src/responder/nss/nss_protocol_grent.c
index 6f6ae57dd..3550c3f0d 100644
--- a/src/responder/nss/nss_protocol_grent.c
+++ b/src/responder/nss/nss_protocol_grent.c
@@ -33,7 +33,7 @@ nss_get_grent(TALLOC_CTX *mem_ctx,
     errno_t ret;
 
     /* Check object class. */
-    if (!ldb_msg_check_string_attribute(msg, "objectClass",
+    if (!ldb_msg_check_string_attribute(msg, SYSDB_OBJECTCATEGORY,
                                         SYSDB_GROUP_CLASS)) {
         DEBUG(SSSDBG_MINOR_FAILURE, "Wrong object (%s) found on stack!\n",
               ldb_dn_get_linearized(msg->dn));
diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c
index 61357c2bf..3f60967d7 100644
--- a/src/responder/nss/nss_protocol_sid.c
+++ b/src/responder/nss/nss_protocol_sid.c
@@ -30,9 +30,9 @@ find_sss_id_type(struct ldb_message *msg,
     struct ldb_message_element *el;
     struct ldb_val *val = NULL;
 
-    el = ldb_msg_find_element(msg, SYSDB_OBJECTCLASS);
+    el = ldb_msg_find_element(msg, SYSDB_OBJECTCATEGORY);
     if (el == NULL) {
-        DEBUG(SSSDBG_OP_FAILURE, "Objectclass attribute not found.\n");
+        DEBUG(SSSDBG_OP_FAILURE, "Objectcategory attribute not found.\n");
         return EINVAL;
     }
 
diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
index 3187af1b0..80b3bb559 100644
--- a/src/tests/cmocka/test_ad_common.c
+++ b/src/tests/cmocka/test_ad_common.c
@@ -336,7 +336,7 @@ static void test_ad_get_pac_data_from_user_entry(void **state)
 
     ret = ldb_msg_add_string(user_msg, SYSDB_NAME, "username");
     assert_int_equal(ret, EOK);
-    ret = ldb_msg_add_string(user_msg, SYSDB_OBJECTCLASS, "user");
+    ret = ldb_msg_add_string(user_msg, SYSDB_OBJECTCATEGORY, SYSDB_USER_CLASS);
     assert_int_equal(ret, EOK);
     ret = ldb_msg_add_string(user_msg, SYSDB_PAC_BLOB_EXPIRE, "12345");
     assert_int_equal(ret, EOK);
diff --git a/src/tests/cmocka/test_ipa_subdomains_server.c b/src/tests/cmocka/test_ipa_subdomains_server.c
index eccfc2fe1..1e492e86c 100644
--- a/src/tests/cmocka/test_ipa_subdomains_server.c
+++ b/src/tests/cmocka/test_ipa_subdomains_server.c
@@ -455,6 +455,8 @@ static void test_ipa_server_create_trusts_twoway(struct tevent_req *req)
         tevent_req_callback_data(req, struct trust_test_ctx);
     errno_t ret;
     struct sss_domain_info *child_dom;
+    struct ipa_ad_server_ctx *s_trust;
+    struct ipa_ad_server_ctx *c_trust;
 
     ret = ipa_server_create_trusts_recv(req);
     talloc_zfree(req);
@@ -462,9 +464,18 @@ static void test_ipa_server_create_trusts_twoway(struct tevent_req *req)
 
     /* Trust object should be around now */
     assert_non_null(test_ctx->ipa_ctx->server_mode->trusts);
+    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts->next);
 
+    if (strcmp(test_ctx->ipa_ctx->server_mode->trusts->dom->name,
+               SUBDOM_NAME) == 0) {
+        s_trust = test_ctx->ipa_ctx->server_mode->trusts;
+        c_trust = test_ctx->ipa_ctx->server_mode->trusts->next;
+    } else {
+        s_trust = test_ctx->ipa_ctx->server_mode->trusts->next;
+        c_trust = test_ctx->ipa_ctx->server_mode->trusts;
+    }
     /* Two-way trusts should use the system realm */
-    assert_trust_object(test_ctx->ipa_ctx->server_mode->trusts,
+    assert_trust_object(c_trust,
                         CHILD_NAME,
                         DOM_REALM,
                         CHILD_SID,
@@ -472,9 +483,8 @@ static void test_ipa_server_create_trusts_twoway(struct tevent_req *req)
                         TEST_AUTHID,
                         DOM_REALM);
 
-    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts->next);
 
-    assert_trust_object(test_ctx->ipa_ctx->server_mode->trusts->next,
+    assert_trust_object(s_trust,
                         SUBDOM_NAME,
                         DOM_REALM,
                         SUBDOM_SID,
@@ -523,6 +533,8 @@ static void test_ipa_server_trust_init(void **state)
     errno_t ret;
     struct tevent_timer *timeout_handler;
     struct timeval tv;
+    struct ipa_ad_server_ctx *s_trust;
+    struct ipa_ad_server_ctx *c_trust;
 
     add_test_2way_subdomains(test_ctx);
 
@@ -537,13 +549,21 @@ static void test_ipa_server_trust_init(void **state)
     ret = test_ev_loop(test_ctx->tctx);
     assert_int_equal(ret, ERR_OK);
 
-    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts);
-
     /* Trust object should be around now */
     assert_non_null(test_ctx->ipa_ctx->server_mode->trusts);
+    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts->next);
+
+    if (strcmp(test_ctx->ipa_ctx->server_mode->trusts->dom->name,
+               SUBDOM_NAME) == 0) {
+        s_trust = test_ctx->ipa_ctx->server_mode->trusts;
+        c_trust = test_ctx->ipa_ctx->server_mode->trusts->next;
+    } else {
+        s_trust = test_ctx->ipa_ctx->server_mode->trusts->next;
+        c_trust = test_ctx->ipa_ctx->server_mode->trusts;
+    }
 
     /* Two-way trusts should use the system realm */
-    assert_trust_object(test_ctx->ipa_ctx->server_mode->trusts,
+    assert_trust_object(c_trust,
                         CHILD_NAME,
                         DOM_REALM,
                         CHILD_SID,
@@ -551,9 +571,7 @@ static void test_ipa_server_trust_init(void **state)
                         TEST_AUTHID,
                         DOM_REALM);
 
-    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts->next);
-
-    assert_trust_object(test_ctx->ipa_ctx->server_mode->trusts->next,
+    assert_trust_object(s_trust,
                         SUBDOM_NAME,
                         DOM_REALM,
                         SUBDOM_SID,
@@ -708,6 +726,8 @@ static void test_ipa_server_create_trusts_oneway(struct tevent_req *req)
     struct trust_test_ctx *test_ctx = \
         tevent_req_callback_data(req, struct trust_test_ctx);
     errno_t ret;
+    struct ipa_ad_server_ctx *s_trust;
+    struct ipa_ad_server_ctx *c_trust;
 
     ret = ipa_server_create_trusts_recv(req);
     talloc_zfree(req);
@@ -720,9 +740,19 @@ static void test_ipa_server_create_trusts_oneway(struct tevent_req *req)
 
     /* Trust object should be around now */
     assert_non_null(test_ctx->ipa_ctx->server_mode->trusts);
+    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts->next);
+
+    if (strcmp(test_ctx->ipa_ctx->server_mode->trusts->dom->name,
+               SUBDOM_NAME) == 0) {
+        s_trust = test_ctx->ipa_ctx->server_mode->trusts;
+        c_trust = test_ctx->ipa_ctx->server_mode->trusts->next;
+    } else {
+        s_trust = test_ctx->ipa_ctx->server_mode->trusts->next;
+        c_trust = test_ctx->ipa_ctx->server_mode->trusts;
+    }
 
     assert_trust_object(
-        test_ctx->ipa_ctx->server_mode->trusts,
+        c_trust,
         CHILD_NAME,    /* AD domain name */
         CHILD_REALM,   /* AD realm can be child if SDAP realm is parent's */
         CHILD_SID,
@@ -730,10 +760,8 @@ static void test_ipa_server_create_trusts_oneway(struct tevent_req *req)
         ONEWAY_PRINC,     /* Principal shared with parent AD dom */
         SUBDOM_REALM); /* SDAP realm must be AD root domain */
 
-    assert_non_null(test_ctx->ipa_ctx->server_mode->trusts->next);
-
     /* Here all properties point to the AD domain */
-    assert_trust_object(test_ctx->ipa_ctx->server_mode->trusts->next,
+    assert_trust_object(s_trust,
                         SUBDOM_NAME,
                         SUBDOM_REALM,
                         SUBDOM_SID,
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 465266108..fc9936968 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -503,7 +503,7 @@ static int test_search_all_users(struct test_data *data)
     }
 
     ret = sysdb_search_entry(data, data->ctx->sysdb, base_dn,
-                             LDB_SCOPE_SUBTREE, "objectClass=user",
+                             LDB_SCOPE_SUBTREE, SYSDB_UC,
                              data->attrlist, &data->msgs_count, &data->msgs);
     return ret;
 }
@@ -2219,6 +2219,7 @@ START_TEST (test_sysdb_search_all_users)
     struct test_data *data;
     int ret;
     int i;
+    int j;
     char *uid_str;
 
     /* Setup */
@@ -2253,8 +2254,15 @@ START_TEST (test_sysdb_search_all_users)
                     "wrong number of values, found [%d] expected [1]",
                     data->msgs[i]->elements[0].num_values);
 
-        uid_str = talloc_asprintf(data, "%d", 27010 + i);
-        fail_unless(uid_str != NULL, "talloc_asprintf failed.");
+        for (j = 0; j < data->msgs_count; j++) {
+            uid_str = talloc_asprintf(data, "%d", 27010 + j);
+            fail_unless(uid_str != NULL, "talloc_asprintf failed.");
+            if (strncmp(uid_str,
+                        (char *) data->msgs[i]->elements[0].values[0].data,
+                        data->msgs[i]->elements[0].values[0].length)  == 0) {
+                break;
+            }
+        }
         fail_unless(strncmp(uid_str,
                             (char *) data->msgs[i]->elements[0].values[0].data,
                             data->msgs[i]->elements[0].values[0].length)  == 0,
@@ -4411,7 +4419,7 @@ START_TEST(test_SSS_LDB_SEARCH)
 
     /* Non-empty filter */
     SSS_LDB_SEARCH(ret, test_ctx->sysdb->ldb, test_ctx, &res, group_dn,
-                   LDB_SCOPE_BASE, NULL, "objectClass=group");
+                   LDB_SCOPE_BASE, NULL, SYSDB_GC);
 
     fail_unless(ret == EOK, "SSS_LDB_SEARCH error [%d][%s]",
                 ret, strerror(ret));
@@ -5203,7 +5211,7 @@ START_TEST (test_sysdb_search_return_ENOENT)
 
     ret = sysdb_search_entry(test_ctx, test_ctx->sysdb,
                              user_dn, LDB_SCOPE_SUBTREE,
-                             "objectClass=user", NULL,
+                             SYSDB_UC, NULL,
                              &count, &msgs);
     fail_unless(ret == ENOENT, "sysdb_search_entry failed: %d, %s",
                                ret, strerror(ret));
@@ -5215,7 +5223,7 @@ START_TEST (test_sysdb_search_return_ENOENT)
                             data->username);
     fail_if(user_dn == NULL, "sysdb_user_dn failed");
     SSS_LDB_SEARCH(ret, test_ctx->sysdb->ldb, test_ctx, &res, user_dn,
-                   LDB_SCOPE_BASE, NULL, "objectClass=user");
+                   LDB_SCOPE_BASE, NULL, SYSDB_UC);
 
     fail_unless(ret == ENOENT, "SSS_LDB_SEARCH failed: %d, %s",
                                ret, strerror(ret));
diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c
index 80f65bb55..42a2a60fd 100644
--- a/src/tools/sssctl/sssctl_cache.c
+++ b/src/tools/sssctl/sssctl_cache.c
@@ -335,7 +335,8 @@ static const char *sssctl_create_filter(TALLOC_CTX *mem_ctx,
         talloc_free(filter_value_old);
     }
 
-    filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
+    filter = talloc_asprintf(mem_ctx, "(&(%s=%s)(|(%s=%s)(%s=%s)))",
+                             obj_type == CACHED_NETGROUP ? SYSDB_OBJECTCLASS : SYSDB_OBJECTCATEGORY,
                              class, attr_name, filter_value,
                              SYSDB_NAME_ALIAS, filter_value);
 

From fba172f54959b405470313dad2049b72bd040256 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Tue, 14 Nov 2017 13:09:18 +0100
Subject: [PATCH 3/4] sysdb: do not use LDB_SCOPE_ONELEVEL

Currently the index for one-level searches is a huge blob which maps all
parents with all it children. Handling this blob is costly and since all
searches using LDB_SCOPE_ONELEVEL also have a filter with indexed
attributes a sub-tree search would be more efficient. But since libldb
currently first looks at the scope and hence use the one-level index
blob we have to explicitly use LDB_SCOPE_SUBTREE in the callers to use
the more efficient attribute based inxed.

Related to https://pagure.io/SSSD/sssd/issue/3503
---
 src/db/sysdb_autofs.c         | 2 +-
 src/db/sysdb_ranges.c         | 2 +-
 src/db/sysdb_subdomains.c     | 2 +-
 src/responder/ifp/ifp_users.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/db/sysdb_autofs.c b/src/db/sysdb_autofs.c
index b3e9b4ec8..89803a778 100644
--- a/src/db/sysdb_autofs.c
+++ b/src/db/sysdb_autofs.c
@@ -384,7 +384,7 @@ sysdb_autofs_entries_by_map(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    ret = sysdb_search_entry(tmp_ctx, domain->sysdb, mapdn, LDB_SCOPE_ONELEVEL,
+    ret = sysdb_search_entry(tmp_ctx, domain->sysdb, mapdn, LDB_SCOPE_SUBTREE,
                              filter, attrs, &count, &msgs);
     if (ret != EOK && ret != ENOENT) {
         DEBUG(SSSDBG_OP_FAILURE, "sysdb search failed: %d\n", ret);
diff --git a/src/db/sysdb_ranges.c b/src/db/sysdb_ranges.c
index 511e4785d..be3a0d372 100644
--- a/src/db/sysdb_ranges.c
+++ b/src/db/sysdb_ranges.c
@@ -71,7 +71,7 @@ errno_t sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
         goto done;
     }
     ret = ldb_search(sysdb->ldb, tmp_ctx, &res,
-                     basedn, LDB_SCOPE_ONELEVEL,
+                     basedn, LDB_SCOPE_SUBTREE,
                      attrs, "objectclass=%s", SYSDB_ID_RANGE_CLASS);
     if (ret != LDB_SUCCESS) {
         ret = EIO;
diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
index 353561765..0dd05c24c 100644
--- a/src/db/sysdb_subdomains.c
+++ b/src/db/sysdb_subdomains.c
@@ -338,7 +338,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain,
         goto done;
     }
     ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
-                     basedn, LDB_SCOPE_ONELEVEL,
+                     basedn, LDB_SCOPE_SUBTREE,
                      attrs, "objectclass=%s", SYSDB_SUBDOMAIN_CLASS);
     if (ret != LDB_SUCCESS) {
         ret = EIO;
diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
index cb342a245..f66587b8c 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -1449,7 +1449,7 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req,
     }
 
     ret = sysdb_search_entry(sbus_req, domain->sysdb, basedn,
-                             LDB_SCOPE_ONELEVEL, filter,
+                             LDB_SCOPE_SUBTREE, filter,
                              extra, &count, &user);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user [%d]: %s\n",

From f15d89aa09d4c5372ac436a66da9326ae27cc518 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Tue, 14 Nov 2017 13:14:14 +0100
Subject: [PATCH 4/4] sysdb: remove IDXONE and objectClass from users and
 groups

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
---
 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 44a7918f6..74ad23f30 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 7c3347fec..5e3b80df4 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 365d45f7e..bc157a246 100644
--- a/src/db/sysdb_upgrade.c
+++ b/src/db/sysdb_upgrade.c
@@ -2317,6 +2317,223 @@ int sysdb_upgrade_18(struct sysdb_ctx *sysdb, const char **ver)
     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.
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org

Reply via email to