From 0f907d8501387ec32dbb00e1c38d5da25e698f90 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 14 Nov 2017 13:14:14 +0100 Subject: [PATCH 57/57] sysdb: remove IDXONE and objectClass from users and groups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch does the needed sysdb update for the previous to patches. It removes the one-level search index IDXONE and replaces objectClass with objectCategory in the user and group objects. Related to https://pagure.io/SSSD/sssd/issue/3503 Reviewed-by: Fabiano FidĂȘncio Reviewed-by: Jakub Hrozek (cherry picked from commit 2927da49dd8a16fff6312d89ad43cc355655800c) --- src/db/sysdb_init.c | 52 +++++++++++- src/db/sysdb_private.h | 11 ++- src/db/sysdb_upgrade.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+), 6 deletions(-) diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c index 44a7918f603fe1368b7d81738666de6bb47b83d0..74ad23f3050da0ae14fa495d2302f4a858fcd3c5 100644 --- a/src/db/sysdb_init.c +++ b/src/db/sysdb_init.c @@ -359,8 +359,48 @@ static errno_t sysdb_ts_cache_upgrade(TALLOC_CTX *mem_ctx, const char *cur_version, const char **_new_version) { - /* Currently the sysdb cache only has one version */ - return EFAULT; + errno_t ret; + TALLOC_CTX *tmp_ctx; + const char *version; + struct ldb_context *save_ldb; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + /* The upgrade process depends on having ldb around, yet the upgrade + * function shouldn't set the ldb pointer, only the connect function + * should after it's successful. To avoid hard refactoring, save the + * ldb pointer here and restore in the 'done' handler + */ + save_ldb = sysdb->ldb; + sysdb->ldb = ldb; + + version = talloc_strdup(tmp_ctx, cur_version); + if (version == NULL) { + ret = ENOMEM; + goto done; + } + + DEBUG(SSSDBG_CONF_SETTINGS, + "Upgrading timstamp cache of DB [%s] from version: %s\n", + domain->name, version); + + if (strcmp(version, SYSDB_TS_VERSION_0_1) == 0) { + ret = sysdb_ts_upgrade_01(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + ret = EOK; + +done: + sysdb->ldb = save_ldb; + *_new_version = version; + talloc_free(tmp_ctx); + return ret; } static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx, @@ -511,6 +551,14 @@ static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx, } } + if (strcmp(version, SYSDB_VERSION_0_19) == 0) { + ret = sysdb_upgrade_19(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + ret = EOK; done: sysdb->ldb = save_ldb; diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h index dbd75615bc212e73c4338a76dceaa68a5889ed1d..cac06ba46da23080d1ab661502d0792bd37b9291 100644 --- a/src/db/sysdb_private.h +++ b/src/db/sysdb_private.h @@ -23,6 +23,7 @@ #ifndef __INT_SYS_DB_H__ #define __INT_SYS_DB_H__ +#define SYSDB_VERSION_0_20 "0.20" #define SYSDB_VERSION_0_19 "0.19" #define SYSDB_VERSION_0_18 "0.18" #define SYSDB_VERSION_0_17 "0.17" @@ -43,7 +44,7 @@ #define SYSDB_VERSION_0_2 "0.2" #define SYSDB_VERSION_0_1 "0.1" -#define SYSDB_VERSION SYSDB_VERSION_0_19 +#define SYSDB_VERSION SYSDB_VERSION_0_20 #define SYSDB_BASE_LDIF \ "dn: @ATTRIBUTES\n" \ @@ -72,7 +73,6 @@ "@IDXATTR: sudoUser\n" \ "@IDXATTR: sshKnownHostsExpire\n" \ "@IDXATTR: objectSIDString\n" \ - "@IDXONE: 1\n" \ "@IDXATTR: ghost\n" \ "@IDXATTR: userPrincipalName\n" \ "@IDXATTR: canonicalUserPrincipalName\n" \ @@ -92,9 +92,10 @@ "\n" /* The timestamp cache has its own versioning */ +#define SYSDB_TS_VERSION_0_2 "0.2" #define SYSDB_TS_VERSION_0_1 "0.1" -#define SYSDB_TS_VERSION SYSDB_TS_VERSION_0_1 +#define SYSDB_TS_VERSION SYSDB_TS_VERSION_0_2 #define SYSDB_TS_BASE_LDIF \ "dn: @ATTRIBUTES\n" \ @@ -103,7 +104,6 @@ "dn: @INDEXLIST\n" \ "@IDXATTR: lastUpdate\n" \ "@IDXATTR: dataExpireTimestamp\n" \ - "@IDXONE: 1\n" \ "\n" \ "dn: cn=sysdb\n" \ "cn: sysdb\n" \ @@ -169,6 +169,9 @@ int sysdb_upgrade_17(struct sysdb_ctx *sysdb, struct sysdb_dom_upgrade_ctx *upgrade_ctx, const char **ver); int sysdb_upgrade_18(struct sysdb_ctx *sysdb, const char **ver); +int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver); + +int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver); int sysdb_add_string(struct ldb_message *msg, const char *attr, const char *value); diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c index 365d45f7ebd78523ca9ec4b9c2158cc09acb5489..bc157a24664239bc1255e49a1825243a07acc90f 100644 --- a/src/db/sysdb_upgrade.c +++ b/src/db/sysdb_upgrade.c @@ -2317,6 +2317,223 @@ done: return ret; } +static errno_t add_object_category(struct ldb_context *ldb, + struct upgrade_ctx *ctx) +{ + errno_t ret; + struct ldb_result *objects = NULL; + const char *attrs[] = { SYSDB_OBJECTCLASS, NULL }; + struct ldb_dn *base_dn; + size_t c; + const char *class_name; + struct ldb_message *msg = NULL; + struct ldb_message *del_msg = NULL; + + base_dn = ldb_dn_new(ctx, ldb, SYSDB_BASE); + if (base_dn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed create base dn.\n"); + return ENOMEM; + } + + ret = ldb_search(ldb, ctx, &objects, base_dn, + LDB_SCOPE_SUBTREE, attrs, + "(|("SYSDB_OBJECTCLASS"="SYSDB_USER_CLASS")" + "("SYSDB_OBJECTCLASS"="SYSDB_GROUP_CLASS"))"); + talloc_free(base_dn); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to search objects: %d\n", ret); + ret = sysdb_error_to_errno(ret); + goto done; + } + + if (objects == NULL || objects->count == 0) { + DEBUG(SSSDBG_TRACE_LIBS, "No objects found, nothing to do."); + ret = EOK; + goto done; + } + + del_msg = ldb_msg_new(ctx); + if (del_msg == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n"); + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_empty(del_msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_DELETE, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + DEBUG(SSSDBG_TRACE_ALL, "Found [%d] objects.\n", objects->count); + for (c = 0; c < objects->count; c++) { + DEBUG(SSSDBG_TRACE_ALL, "Updating [%s].\n", + ldb_dn_get_linearized(objects->msgs[c]->dn)); + + class_name = ldb_msg_find_attr_as_string(objects->msgs[c], + SYSDB_OBJECTCLASS, NULL); + if (class_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Searched objects by objectClass, " + "but result does not have one.\n"); + ret = EINVAL; + goto done; + } + + talloc_free(msg); + msg = ldb_msg_new(ctx); + if (msg == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n"); + ret = ENOMEM; + goto done; + } + + msg->dn = objects->msgs[c]->dn; + del_msg->dn = objects->msgs[c]->dn; + + ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCATEGORY, LDB_FLAG_MOD_ADD, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_string(msg, SYSDB_OBJECTCATEGORY, class_name); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + DEBUG(SSSDBG_TRACE_ALL, "Adding [%s] to [%s].\n", class_name, + ldb_dn_get_linearized(objects->msgs[c]->dn)); + ret = ldb_modify(ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to add objectCategory to %s: %d.\n", + ldb_dn_get_linearized(objects->msgs[c]->dn), + sysdb_error_to_errno(ret)); + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_modify(ldb, del_msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to remove objectClass from %s: %d.\n", + ldb_dn_get_linearized(objects->msgs[c]->dn), + sysdb_error_to_errno(ret)); + ret = sysdb_error_to_errno(ret); + goto done; + } + } + + ret = EOK; + +done: + talloc_free(msg); + talloc_free(del_msg); + talloc_free(objects); + + return ret; +} + +int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver) +{ + struct upgrade_ctx *ctx; + errno_t ret; + struct ldb_message *msg = NULL; + + ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_20, &ctx); + if (ret) { + return ret; + } + + ret = add_object_category(sysdb->ldb, ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "add_object_category failed.\n"); + goto done; + } + + /* Remove @IDXONE from index */ + msg = ldb_msg_new(ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST"); + if (msg->dn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "@IDXONE", LDB_FLAG_MOD_DELETE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_modify(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + /* conversion done, update version number */ + ret = update_version(ctx); + +done: + ret = finish_upgrade(ret, &ctx, ver); + return ret; +} + +int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver) +{ + struct upgrade_ctx *ctx; + errno_t ret; + struct ldb_message *msg = NULL; + + ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_TS_VERSION_0_2, &ctx); + if (ret) { + return ret; + } + + /* Remove @IDXONE from index */ + talloc_free(msg); + msg = ldb_msg_new(ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST"); + if (msg->dn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "@IDXONE", LDB_FLAG_MOD_DELETE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_modify(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + /* conversion done, update version number */ + ret = update_version(ctx); + +done: + ret = finish_upgrade(ret, &ctx, ver); + return ret; +} + /* * Example template for future upgrades. * Copy and change version numbers as appropriate. -- 2.14.3