summaryrefslogtreecommitdiff
path: root/src/db
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2011-10-05 13:57:24 -0400
committerStephen Gallagher <sgallagh@redhat.com>2011-10-07 14:29:00 -0400
commitc2352a73f52f600d95966ebe0b0819649ba923fa (patch)
treebbcd6ac369f49317244b01a67fdb20dfbeec062f /src/db
parent73851471133f0345945a4232c5dc147be26f9941 (diff)
downloadsssd-c2352a73f52f600d95966ebe0b0819649ba923fa.tar.gz
sssd-c2352a73f52f600d95966ebe0b0819649ba923fa.tar.bz2
sssd-c2352a73f52f600d95966ebe0b0819649ba923fa.zip
SYSDB: New source file for sysdb upgrade routines
Diffstat (limited to 'src/db')
-rw-r--r--src/db/sysdb.c900
-rw-r--r--src/db/sysdb_private.h21
-rw-r--r--src/db/sysdb_upgrade.c896
3 files changed, 929 insertions, 888 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 1a326030..54a4257c 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 0cbb3a45..bb98181a 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 00000000..c8933223
--- /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;
+}