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 14a145072ea5e203bf1612dc56a64bbe60e0d453 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 d8adc7a2e2125c7aeaf180376c35a23843b10562 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/ad/ad_pac.c                          |  2 +-
 src/providers/ipa/ipa_id.c                         |  9 ++--
 src/providers/ipa/ipa_subdomains_ext_groups.c      |  2 +-
 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             |  8 ++--
 src/providers/ldap/sdap_async_initgroups.c         |  2 +-
 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                     |  4 +-
 src/responder/ifp/ifp_users.c                      |  2 +-
 src/responder/nss/nss_cmd.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 +-
 27 files changed, 110 insertions(+), 65 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/ad/ad_pac.c b/src/providers/ad/ad_pac.c
index ed002e1f9..6b47462cf 100644
--- a/src/providers/ad/ad_pac.c
+++ b/src/providers/ad/ad_pac.c
@@ -31,7 +31,7 @@ static errno_t find_user_entry(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
                                struct dp_id_data *ar,
                                struct ldb_message **_msg)
 {
-    const char *user_attrs[] = { SYSDB_NAME, SYSDB_OBJECTCLASS,
+    const char *user_attrs[] = { SYSDB_NAME, SYSDB_OBJECTCATEGORY,
                                  SYSDB_PAC_BLOB, SYSDB_PAC_BLOB_EXPIRE,
                                  NULL };
     struct ldb_message *msg;
diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
index 5044577f0..8f8759f64 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) {
@@ -733,7 +734,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
     const char *attrs[] = { SYSDB_NAME,
                             SYSDB_UIDNUM,
                             SYSDB_SID_STR,
-                            SYSDB_OBJECTCLASS,
+                            SYSDB_OBJECTCATEGORY,
                             SYSDB_UUID,
                             SYSDB_GHOST,
                             SYSDB_HOMEDIR,
@@ -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_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c
index 0359e0ded..9e1d6c3a9 100644
--- a/src/providers/ipa/ipa_subdomains_ext_groups.c
+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c
@@ -940,7 +940,7 @@ search_user_or_group_by_sid_str(TALLOC_CTX *mem_ctx,
     const char *attrs[] = { SYSDB_NAME,
                             SYSDB_SID_STR,
                             SYSDB_ORIG_DN,
-                            SYSDB_OBJECTCLASS,
+                            SYSDB_OBJECTCATEGORY,
                             SYSDB_CACHE_EXPIRE,
                             NULL };
     TALLOC_CTX *tmp_ctx = NULL;
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..b1cfb7e4a 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,11 +90,11 @@ 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",
-                  SYSDB_OBJECTCLASS);
+            DEBUG(SSSDBG_OP_FAILURE, "An entry without a %s?\n",
+                  SYSDB_OBJECTCATEGORY);
             ret = EINVAL;
             goto done;
         }
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index a33975cde..f8a844747 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2341,7 +2341,7 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req)
     }
 
     ret = sysdb_attrs_get_string(state->groups[state->group_iter],
-                                 SYSDB_OBJECTCLASS, &class);
+                                 SYSDB_OBJECTCATEGORY, &class);
     if (ret == EOK) {
         /* If there is a objectClass attribute the object is coming from the
          * cache and the name attribute of the object already has the primary
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..b274b8f52 100644
--- a/src/responder/ifp/ifp_groups.c
+++ b/src/responder/ifp/ifp_groups.c
@@ -841,7 +841,7 @@ ifp_groups_group_get_members(TALLOC_CTX *mem_ctx,
     int num_groups;
     int i;
     errno_t ret;
-    const char *attrs[] = {SYSDB_OBJECTCLASS, SYSDB_UIDNUM,
+    const char *attrs[] = {SYSDB_OBJECTCATEGORY, SYSDB_UIDNUM,
                            SYSDB_GIDNUM, NULL};
 
     tmp_ctx = talloc_new(NULL);
@@ -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_cmd.c b/src/responder/nss/nss_cmd.c
index 545257a0b..956ee53cb 100644
--- a/src/responder/nss/nss_cmd.c
+++ b/src/responder/nss/nss_cmd.c
@@ -1148,7 +1148,7 @@ static errno_t nss_cmd_getorigbyname(struct cli_ctx *cli_ctx)
     errno_t ret;
     struct nss_ctx *nss_ctx;
     const char **attrs;
-    static const char *defattrs[] = { SYSDB_NAME, SYSDB_OBJECTCLASS,
+    static const char *defattrs[] = { SYSDB_NAME, SYSDB_OBJECTCATEGORY,
                                       SYSDB_SID_STR,
                                       ORIGINALAD_PREFIX SYSDB_NAME,
                                       ORIGINALAD_PREFIX SYSDB_UIDNUM,
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 0718cbc4e911df79dd76a5491f897bfae751f02c 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 ac0696fd69da00432d1821fe89d95a75b63c2a57 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