diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db/sysdb.c | 900 | ||||
-rw-r--r-- | src/db/sysdb_private.h | 21 | ||||
-rw-r--r-- | src/db/sysdb_upgrade.c | 896 |
3 files changed, 929 insertions, 888 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c index 1a326030c..54a4257c6 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -3,7 +3,8 @@ System Database - Copyright (C) Simo Sorce <ssorce@redhat.com> 2008 + Copyright (C) 2008-2011 Simo Sorce <ssorce@redhat.com> + Copyright (C) 2008-2011 Stephen Gallagher <ssorce@redhat.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,8 +28,8 @@ #define LDB_MODULES_PATH "LDB_MODULES_PATH" -static errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename, - struct ldb_context **_ldb) +errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename, + struct ldb_context **_ldb) { int ret; struct ldb_context *ldb; @@ -772,15 +773,9 @@ int sysdb_transaction_cancel(struct sysdb_ctx *sysdb) /* =Initialization======================================================== */ -static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - const char *db_path, - bool allow_upgrade, - struct sysdb_ctx **_ctx); - -static int sysdb_get_db_file(TALLOC_CTX *mem_ctx, - const char *provider, const char *name, - const char *base_path, char **_ldb_file) +int sysdb_get_db_file(TALLOC_CTX *mem_ctx, + const char *provider, const char *name, + const char *base_path, char **_ldb_file) { char *ldb_file; @@ -800,882 +795,11 @@ static int sysdb_get_db_file(TALLOC_CTX *mem_ctx, return EOK; } -static int finish_upgrade(int result, struct ldb_context *ldb, - const char *next_ver, const char **ver) -{ - int ret = result; - - if (ret == EOK) { - ret = ldb_transaction_commit(ldb); - ret = sysdb_error_to_errno(ret); - if (ret == EOK) { - *ver = next_ver; - } - } - - if (ret != EOK) { - ret = ldb_transaction_cancel(ldb); - ret = sysdb_error_to_errno(ret); - } - - return ret; -} - -/* serach all groups that have a memberUid attribute. - * change it into a member attribute for a user of same domain. - * remove the memberUid attribute - * add the new member attribute - * finally stop indexing memberUid - * upgrade version to 0.2 - */ -static int sysdb_upgrade_01(struct ldb_context *ldb, - const char **ver) -{ - struct ldb_message_element *el; - struct ldb_result *res; - struct ldb_dn *basedn; - struct ldb_dn *mem_dn; - struct ldb_message *msg; - const struct ldb_val *val; - const char *filter = "(&(memberUid=*)(objectclass=group))"; - const char *attrs[] = { "memberUid", NULL }; - const char *mdn; - char *domain; - int ret, i, j; - TALLOC_CTX *tmp_ctx; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - ret = ENOMEM; - goto done; - } - - basedn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); - if (!basedn) { - ret = EIO; - goto done; - } - - ret = ldb_search(ldb, tmp_ctx, &res, - basedn, LDB_SCOPE_SUBTREE, - attrs, filter); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - ret = ldb_transaction_start(ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - for (i = 0; i < res->count; i++) { - el = ldb_msg_find_element(res->msgs[i], "memberUid"); - if (!el) { - DEBUG(1, ("memberUid is missing from message [%s], skipping\n", - ldb_dn_get_linearized(res->msgs[i]->dn))); - continue; - } - - /* create modification message */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = res->msgs[i]->dn; - - ret = ldb_msg_add_empty(msg, "memberUid", LDB_FLAG_MOD_DELETE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - /* get domain name component value */ - val = ldb_dn_get_component_val(res->msgs[i]->dn, 2); - domain = talloc_strndup(tmp_ctx, (const char *)val->data, val->length); - if (!domain) { - ret = ENOMEM; - goto done; - } - - for (j = 0; j < el->num_values; j++) { - mem_dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_USER, - (const char *)el->values[j].data, domain); - if (!mem_dn) { - ret = ENOMEM; - goto done; - } - - mdn = talloc_strdup(msg, ldb_dn_get_linearized(mem_dn)); - if (!mdn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, SYSDB_MEMBER, mdn); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - talloc_zfree(mem_dn); - } - - /* ok now we are ready to modify the entry */ - ret = ldb_modify(ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - talloc_zfree(msg); - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_2); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - ret = EOK; - -done: - ret = finish_upgrade(ret, ldb, SYSDB_VERSION_0_2, ver); - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_check_upgrade_02(struct sss_domain_info *domains, - const char *db_path) -{ - TALLOC_CTX *tmp_ctx = NULL; - struct ldb_context *ldb; - char *ldb_file; - struct sysdb_ctx *sysdb; - struct sss_domain_info *dom; - struct ldb_message_element *el; - struct ldb_message *msg; - struct ldb_result *res; - struct ldb_dn *verdn; - const char *version = NULL; - bool do_02_upgrade = false; - bool ctx_trans = false; - int ret; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - ret = sysdb_get_db_file(tmp_ctx, - "local", "UPGRADE", - db_path, &ldb_file); - if (ret != EOK) { - goto exit; - } - - ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb); - if (ret != EOK) { - DEBUG(1, ("sysdb_ldb_connect failed.\n")); - return ret; - } - - verdn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); - if (!verdn) { - ret = EIO; - goto exit; - } - - ret = ldb_search(ldb, tmp_ctx, &res, - verdn, LDB_SCOPE_BASE, - NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto exit; - } - if (res->count > 1) { - ret = EIO; - goto exit; - } - - if (res->count == 1) { - el = ldb_msg_find_element(res->msgs[0], "version"); - if (el) { - if (el->num_values != 1) { - ret = EINVAL; - goto exit; - } - version = talloc_strndup(tmp_ctx, - (char *)(el->values[0].data), - el->values[0].length); - if (!version) { - ret = ENOMEM; - goto exit; - } - - if (strcmp(version, SYSDB_VERSION) == 0) { - /* all fine, return */ - ret = EOK; - goto exit; - } - - DEBUG(4, ("Upgrading DB from version: %s\n", version)); - - if (strcmp(version, SYSDB_VERSION_0_1) == 0) { - /* convert database */ - ret = sysdb_upgrade_01(ldb, &version); - if (ret != EOK) goto exit; - } - - if (strcmp(version, SYSDB_VERSION_0_2) == 0) { - /* need to convert database to split files */ - do_02_upgrade = true; - } - - } - } - - if (!do_02_upgrade) { - /* not a v2 upgrade, return and let the normal code take over any - * further upgrade */ - ret = EOK; - goto exit; - } - - /* == V2->V3 UPGRADE == */ - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_3)); - - /* ldb uses posix locks, - * posix is stupid and kills all locks when you close *any* file - * descriptor associated to the same file. - * Therefore we must close and reopen the ldb file here */ - - /* == Backup and reopen ldb == */ - - /* close */ - talloc_zfree(ldb); - - /* backup*/ - ret = backup_file(ldb_file, 0); - if (ret != EOK) { - goto exit; - } - - /* reopen */ - ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb); - if (ret != EOK) { - DEBUG(1, ("sysdb_ldb_connect failed.\n")); - return ret; - } - - /* open a transaction */ - ret = ldb_transaction_start(ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); - ret = EIO; - goto exit; - } - - /* == Upgrade contents == */ - - for (dom = domains; dom; dom = dom->next) { - struct ldb_dn *domain_dn; - struct ldb_dn *users_dn; - struct ldb_dn *groups_dn; - int i; - - /* skip local */ - if (strcasecmp(dom->provider, "local") == 0) { - continue; - } - - /* create new dom db */ - ret = sysdb_domain_init_internal(tmp_ctx, dom, - db_path, false, &sysdb); - if (ret != EOK) { - goto done; - } - - ret = ldb_transaction_start(sysdb->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); - ret = EIO; - goto done; - } - ctx_trans = true; - - /* search all entries for this domain in local, - * copy them all in the new database, - * then remove them from local */ - - domain_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, - SYSDB_DOM_BASE, sysdb->domain->name); - if (!domain_dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_search(ldb, tmp_ctx, &res, - domain_dn, LDB_SCOPE_SUBTREE, - NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - users_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, - SYSDB_TMPL_USER_BASE, sysdb->domain->name); - if (!users_dn) { - ret = ENOMEM; - goto done; - } - groups_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, - SYSDB_TMPL_GROUP_BASE, sysdb->domain->name); - if (!groups_dn) { - ret = ENOMEM; - goto done; - } - - for (i = 0; i < res->count; i++) { - - struct ldb_dn *orig_dn; - - msg = res->msgs[i]; - - /* skip pre-created congtainers */ - if ((ldb_dn_compare(msg->dn, domain_dn) == 0) || - (ldb_dn_compare(msg->dn, users_dn) == 0) || - (ldb_dn_compare(msg->dn, groups_dn) == 0)) { - continue; - } - - /* regenerate the DN against the new ldb as it may have different - * casefolding rules (example: name changing from case insensitive - * to case sensitive) */ - orig_dn = msg->dn; - msg->dn = ldb_dn_new(msg, sysdb->ldb, - ldb_dn_get_linearized(orig_dn)); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_add(sysdb->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("WARNING: Could not add entry %s," - " to new ldb file! (%d [%s])\n", - ldb_dn_get_linearized(msg->dn), - ret, ldb_errstring(sysdb->ldb))); - } - - ret = ldb_delete(ldb, orig_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(orig_dn), - ret, ldb_errstring(ldb))); - } - } - - /* now remove the basic containers from local */ - /* these were optional so debug at level 9 in case - * of failure just for tracing */ - ret = ldb_delete(ldb, groups_dn); - if (ret != LDB_SUCCESS) { - DEBUG(9, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(groups_dn), - ret, ldb_errstring(ldb))); - } - ret = ldb_delete(ldb, users_dn); - if (ret != LDB_SUCCESS) { - DEBUG(9, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(users_dn), - ret, ldb_errstring(ldb))); - } - ret = ldb_delete(ldb, domain_dn); - if (ret != LDB_SUCCESS) { - DEBUG(9, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(domain_dn), - ret, ldb_errstring(ldb))); - } - - ret = ldb_transaction_commit(sysdb->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); - ret = EIO; - goto done; - } - ctx_trans = false; - - talloc_zfree(domain_dn); - talloc_zfree(groups_dn); - talloc_zfree(users_dn); - talloc_zfree(res); - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_3); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - ret = ldb_transaction_commit(ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); - ret = EIO; - goto exit; - } - - ret = EOK; - -done: - if (ret != EOK) { - if (ctx_trans) { - ret = ldb_transaction_cancel(sysdb->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); - } - } - ret = ldb_transaction_cancel(ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); - } - } - -exit: - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_upgrade_03(struct sysdb_ctx *sysdb, const char **ver) -{ - TALLOC_CTX *tmp_ctx; - int ret; - struct ldb_message *msg; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_4)); - - ret = ldb_transaction_start(sysdb->ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - /* Make this database case-sensitive */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "name", 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, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_4); - 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; - } - - ret = EOK; - -done: - ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_4, ver); - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_upgrade_04(struct sysdb_ctx *sysdb, const char **ver) -{ - TALLOC_CTX *tmp_ctx; - int ret; - struct ldb_message *msg; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_5)); - - ret = ldb_transaction_start(sysdb->ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - /* Add new index */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@INDEXLIST"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "@IDXATTR", "originalDN"); - 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; - } - - /* Rebuild memberuid and memberoif attributes */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@MEMBEROF-REBUILD"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_add(sysdb->ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_5); - 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; - } - - ret = EOK; - -done: - ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_5, ver); - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_upgrade_05(struct sysdb_ctx *sysdb, const char **ver) -{ - TALLOC_CTX *tmp_ctx; - int ret; - struct ldb_message *msg; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_6)); - - ret = ldb_transaction_start(sysdb->ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - /* Add new indexes */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@INDEXLIST"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - /* Add Index for dataExpireTimestamp */ - ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "@IDXATTR", "dataExpireTimestamp"); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - /* Add index to speed up ONELEVEL searches */ - ret = ldb_msg_add_empty(msg, "@IDXONE", LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "@IDXONE", "1"); - 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, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_6); - 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; - } - - ret = EOK; - -done: - ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_6, ver); - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_upgrade_06(struct sysdb_ctx *sysdb, const char **ver) -{ - TALLOC_CTX *tmp_ctx; - int ret; - struct ldb_message *msg; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_7)); - - ret = ldb_transaction_start(sysdb->ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - /* Add new indexes */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - /* Case insensitive search for originalDN */ - ret = ldb_msg_add_empty(msg, SYSDB_ORIG_DN, LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, SYSDB_ORIG_DN, "CASE_INSENSITIVE"); - 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, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "cn=sysdb"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_7); - 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; - } - - ret = EOK; - -done: - ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_7, ver); - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - const char *db_path, - bool allow_upgrade, - struct sysdb_ctx **_ctx) +int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *db_path, + bool allow_upgrade, + struct sysdb_ctx **_ctx) { TALLOC_CTX *tmp_ctx = NULL; struct sysdb_ctx *sysdb; diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h index 0cbb3a45a..bb98181a1 100644 --- a/src/db/sysdb_private.h +++ b/src/db/sysdb_private.h @@ -74,4 +74,25 @@ struct sysdb_ctx { char *ldb_file; }; +/* Internal utility functions */ +int sysdb_get_db_file(TALLOC_CTX *mem_ctx, + const char *provider, const char *name, + const char *base_path, char **_ldb_file); +errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename, + struct ldb_context **_ldb); +int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *db_path, + bool allow_upgrade, + struct sysdb_ctx **_ctx); + +/* Upgrade routines */ +int sysdb_upgrade_01(struct ldb_context *ldb, const char **ver); +int sysdb_check_upgrade_02(struct sss_domain_info *domains, + const char *db_path); +int sysdb_upgrade_03(struct sysdb_ctx *sysdb, const char **ver); +int sysdb_upgrade_04(struct sysdb_ctx *sysdb, const char **ver); +int sysdb_upgrade_05(struct sysdb_ctx *sysdb, const char **ver); +int sysdb_upgrade_06(struct sysdb_ctx *sysdb, const char **ver); + #endif /* __INT_SYS_DB_H__ */ diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c new file mode 100644 index 000000000..c89332236 --- /dev/null +++ b/src/db/sysdb_upgrade.c @@ -0,0 +1,896 @@ +/* + SSSD + + Authors: + Simo Sorce <ssorce@redhat.com> + Stephen Gallagher <sgallagh@redhat.com> + + Copyright (C) 2008-2011 Simo Sorce <ssorce@redhat.com> + Copyright (C) 2008-2011 Stephen Gallagher + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "util/util.h" +#include "db/sysdb_private.h" + +static int finish_upgrade(int result, struct ldb_context *ldb, + const char *next_ver, const char **ver) +{ + int ret = result; + + if (ret == EOK) { + ret = ldb_transaction_commit(ldb); + ret = sysdb_error_to_errno(ret); + if (ret == EOK) { + *ver = next_ver; + } + } + + if (ret != EOK) { + ret = ldb_transaction_cancel(ldb); + ret = sysdb_error_to_errno(ret); + } + + return ret; +} + +/* serach all groups that have a memberUid attribute. + * change it into a member attribute for a user of same domain. + * remove the memberUid attribute + * add the new member attribute + * finally stop indexing memberUid + * upgrade version to 0.2 + */ +int sysdb_upgrade_01(struct ldb_context *ldb, const char **ver) +{ + struct ldb_message_element *el; + struct ldb_result *res; + struct ldb_dn *basedn; + struct ldb_dn *mem_dn; + struct ldb_message *msg; + const struct ldb_val *val; + const char *filter = "(&(memberUid=*)(objectclass=group))"; + const char *attrs[] = { "memberUid", NULL }; + const char *mdn; + char *domain; + int ret, i, j; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + ret = ENOMEM; + goto done; + } + + basedn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); + if (!basedn) { + ret = EIO; + goto done; + } + + ret = ldb_search(ldb, tmp_ctx, &res, + basedn, LDB_SCOPE_SUBTREE, + attrs, filter); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + ret = ldb_transaction_start(ldb); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + for (i = 0; i < res->count; i++) { + el = ldb_msg_find_element(res->msgs[i], "memberUid"); + if (!el) { + DEBUG(1, ("memberUid is missing from message [%s], skipping\n", + ldb_dn_get_linearized(res->msgs[i]->dn))); + continue; + } + + /* create modification message */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = res->msgs[i]->dn; + + ret = ldb_msg_add_empty(msg, "memberUid", LDB_FLAG_MOD_DELETE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + /* get domain name component value */ + val = ldb_dn_get_component_val(res->msgs[i]->dn, 2); + domain = talloc_strndup(tmp_ctx, (const char *)val->data, val->length); + if (!domain) { + ret = ENOMEM; + goto done; + } + + for (j = 0; j < el->num_values; j++) { + mem_dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_USER, + (const char *)el->values[j].data, domain); + if (!mem_dn) { + ret = ENOMEM; + goto done; + } + + mdn = talloc_strdup(msg, ldb_dn_get_linearized(mem_dn)); + if (!mdn) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, SYSDB_MEMBER, mdn); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + talloc_zfree(mem_dn); + } + + /* ok now we are ready to modify the entry */ + ret = ldb_modify(ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + talloc_zfree(msg); + } + + /* conversion done, upgrade version number */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_2); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_modify(ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = EOK; + +done: + ret = finish_upgrade(ret, ldb, SYSDB_VERSION_0_2, ver); + talloc_free(tmp_ctx); + return ret; +} + +int sysdb_check_upgrade_02(struct sss_domain_info *domains, + const char *db_path) +{ + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_context *ldb; + char *ldb_file; + struct sysdb_ctx *sysdb; + struct sss_domain_info *dom; + struct ldb_message_element *el; + struct ldb_message *msg; + struct ldb_result *res; + struct ldb_dn *verdn; + const char *version = NULL; + bool do_02_upgrade = false; + bool ctx_trans = false; + int ret; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + ret = sysdb_get_db_file(tmp_ctx, + "local", "UPGRADE", + db_path, &ldb_file); + if (ret != EOK) { + goto exit; + } + + ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb); + if (ret != EOK) { + DEBUG(1, ("sysdb_ldb_connect failed.\n")); + return ret; + } + + verdn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); + if (!verdn) { + ret = EIO; + goto exit; + } + + ret = ldb_search(ldb, tmp_ctx, &res, + verdn, LDB_SCOPE_BASE, + NULL, NULL); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto exit; + } + if (res->count > 1) { + ret = EIO; + goto exit; + } + + if (res->count == 1) { + el = ldb_msg_find_element(res->msgs[0], "version"); + if (el) { + if (el->num_values != 1) { + ret = EINVAL; + goto exit; + } + version = talloc_strndup(tmp_ctx, + (char *)(el->values[0].data), + el->values[0].length); + if (!version) { + ret = ENOMEM; + goto exit; + } + + if (strcmp(version, SYSDB_VERSION) == 0) { + /* all fine, return */ + ret = EOK; + goto exit; + } + + DEBUG(4, ("Upgrading DB from version: %s\n", version)); + + if (strcmp(version, SYSDB_VERSION_0_1) == 0) { + /* convert database */ + ret = sysdb_upgrade_01(ldb, &version); + if (ret != EOK) goto exit; + } + + if (strcmp(version, SYSDB_VERSION_0_2) == 0) { + /* need to convert database to split files */ + do_02_upgrade = true; + } + + } + } + + if (!do_02_upgrade) { + /* not a v2 upgrade, return and let the normal code take over any + * further upgrade */ + ret = EOK; + goto exit; + } + + /* == V2->V3 UPGRADE == */ + + DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_3)); + + /* ldb uses posix locks, + * posix is stupid and kills all locks when you close *any* file + * descriptor associated to the same file. + * Therefore we must close and reopen the ldb file here */ + + /* == Backup and reopen ldb == */ + + /* close */ + talloc_zfree(ldb); + + /* backup*/ + ret = backup_file(ldb_file, 0); + if (ret != EOK) { + goto exit; + } + + /* reopen */ + ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb); + if (ret != EOK) { + DEBUG(1, ("sysdb_ldb_connect failed.\n")); + return ret; + } + + /* open a transaction */ + ret = ldb_transaction_start(ldb); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); + ret = EIO; + goto exit; + } + + /* == Upgrade contents == */ + + for (dom = domains; dom; dom = dom->next) { + struct ldb_dn *domain_dn; + struct ldb_dn *users_dn; + struct ldb_dn *groups_dn; + int i; + + /* skip local */ + if (strcasecmp(dom->provider, "local") == 0) { + continue; + } + + /* create new dom db */ + ret = sysdb_domain_init_internal(tmp_ctx, dom, + db_path, false, &sysdb); + if (ret != EOK) { + goto done; + } + + ret = ldb_transaction_start(sysdb->ldb); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); + ret = EIO; + goto done; + } + ctx_trans = true; + + /* search all entries for this domain in local, + * copy them all in the new database, + * then remove them from local */ + + domain_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, + SYSDB_DOM_BASE, sysdb->domain->name); + if (!domain_dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_search(ldb, tmp_ctx, &res, + domain_dn, LDB_SCOPE_SUBTREE, + NULL, NULL); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + users_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, + SYSDB_TMPL_USER_BASE, sysdb->domain->name); + if (!users_dn) { + ret = ENOMEM; + goto done; + } + groups_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, + SYSDB_TMPL_GROUP_BASE, sysdb->domain->name); + if (!groups_dn) { + ret = ENOMEM; + goto done; + } + + for (i = 0; i < res->count; i++) { + + struct ldb_dn *orig_dn; + + msg = res->msgs[i]; + + /* skip pre-created congtainers */ + if ((ldb_dn_compare(msg->dn, domain_dn) == 0) || + (ldb_dn_compare(msg->dn, users_dn) == 0) || + (ldb_dn_compare(msg->dn, groups_dn) == 0)) { + continue; + } + + /* regenerate the DN against the new ldb as it may have different + * casefolding rules (example: name changing from case insensitive + * to case sensitive) */ + orig_dn = msg->dn; + msg->dn = ldb_dn_new(msg, sysdb->ldb, + ldb_dn_get_linearized(orig_dn)); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(0, ("WARNING: Could not add entry %s," + " to new ldb file! (%d [%s])\n", + ldb_dn_get_linearized(msg->dn), + ret, ldb_errstring(sysdb->ldb))); + } + + ret = ldb_delete(ldb, orig_dn); + if (ret != LDB_SUCCESS) { + DEBUG(0, ("WARNING: Could not remove entry %s," + " from old ldb file! (%d [%s])\n", + ldb_dn_get_linearized(orig_dn), + ret, ldb_errstring(ldb))); + } + } + + /* now remove the basic containers from local */ + /* these were optional so debug at level 9 in case + * of failure just for tracing */ + ret = ldb_delete(ldb, groups_dn); + if (ret != LDB_SUCCESS) { + DEBUG(9, ("WARNING: Could not remove entry %s," + " from old ldb file! (%d [%s])\n", + ldb_dn_get_linearized(groups_dn), + ret, ldb_errstring(ldb))); + } + ret = ldb_delete(ldb, users_dn); + if (ret != LDB_SUCCESS) { + DEBUG(9, ("WARNING: Could not remove entry %s," + " from old ldb file! (%d [%s])\n", + ldb_dn_get_linearized(users_dn), + ret, ldb_errstring(ldb))); + } + ret = ldb_delete(ldb, domain_dn); + if (ret != LDB_SUCCESS) { + DEBUG(9, ("WARNING: Could not remove entry %s," + " from old ldb file! (%d [%s])\n", + ldb_dn_get_linearized(domain_dn), + ret, ldb_errstring(ldb))); + } + + ret = ldb_transaction_commit(sysdb->ldb); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); + ret = EIO; + goto done; + } + ctx_trans = false; + + talloc_zfree(domain_dn); + talloc_zfree(groups_dn); + talloc_zfree(users_dn); + talloc_zfree(res); + } + + /* conversion done, upgrade version number */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, ldb, SYSDB_BASE); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_3); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_modify(ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_transaction_commit(ldb); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); + ret = EIO; + goto exit; + } + + ret = EOK; + +done: + if (ret != EOK) { + if (ctx_trans) { + ret = ldb_transaction_cancel(sysdb->ldb); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); + } + } + ret = ldb_transaction_cancel(ldb); + if (ret != LDB_SUCCESS) { + DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); + } + } + +exit: + talloc_free(tmp_ctx); + return ret; +} + +int sysdb_upgrade_03(struct sysdb_ctx *sysdb, const char **ver) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_message *msg; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_4)); + + ret = ldb_transaction_start(sysdb->ldb); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + /* Make this database case-sensitive */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "name", 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, upgrade version number */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_4); + 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; + } + + ret = EOK; + +done: + ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_4, ver); + talloc_free(tmp_ctx); + return ret; +} + +int sysdb_upgrade_04(struct sysdb_ctx *sysdb, const char **ver) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_message *msg; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_5)); + + ret = ldb_transaction_start(sysdb->ldb); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + /* Add new index */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@INDEXLIST"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "@IDXATTR", "originalDN"); + 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; + } + + /* Rebuild memberuid and memberoif attributes */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@MEMBEROF-REBUILD"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + /* conversion done, upgrade version number */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_5); + 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; + } + + ret = EOK; + +done: + ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_5, ver); + talloc_free(tmp_ctx); + return ret; +} + +int sysdb_upgrade_05(struct sysdb_ctx *sysdb, const char **ver) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_message *msg; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_6)); + + ret = ldb_transaction_start(sysdb->ldb); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + /* Add new indexes */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@INDEXLIST"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + /* Add Index for dataExpireTimestamp */ + ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "@IDXATTR", "dataExpireTimestamp"); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + /* Add index to speed up ONELEVEL searches */ + ret = ldb_msg_add_empty(msg, "@IDXONE", LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "@IDXONE", "1"); + 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, upgrade version number */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_6); + 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; + } + + ret = EOK; + +done: + ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_6, ver); + talloc_free(tmp_ctx); + return ret; +} + +int sysdb_upgrade_06(struct sysdb_ctx *sysdb, const char **ver) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_message *msg; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_7)); + + ret = ldb_transaction_start(sysdb->ldb); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + /* Add new indexes */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "@ATTRIBUTES"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + /* Case insensitive search for originalDN */ + ret = ldb_msg_add_empty(msg, SYSDB_ORIG_DN, LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, SYSDB_ORIG_DN, "CASE_INSENSITIVE"); + 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, upgrade version number */ + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(tmp_ctx, sysdb->ldb, "cn=sysdb"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_7); + 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; + } + + ret = EOK; + +done: + ret = finish_upgrade(ret, sysdb->ldb, SYSDB_VERSION_0_7, ver); + talloc_free(tmp_ctx); + return ret; +} |