diff options
author | Simo Sorce <ssorce@redhat.com> | 2009-12-14 15:44:11 -0500 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2009-12-15 08:33:56 -0500 |
commit | b6cfa269d29db06855ecad0484315efbd5b97143 (patch) | |
tree | 9b3e525a2a68686140fe05c03f8229c35b3353ea | |
parent | 5df4f49fef317f4b37a35d6452866e2922ab111c (diff) | |
download | sssd-b6cfa269d29db06855ecad0484315efbd5b97143.tar.gz sssd-b6cfa269d29db06855ecad0484315efbd5b97143.tar.xz sssd-b6cfa269d29db06855ecad0484315efbd5b97143.zip |
Fix upgrade bug #323
Move the upgrade function first and check explicitly for the old ldb name.
Perform upgrades up to v02 first if necessary.
Then proceed as normal letting the normal init functions perform further
upgrades if necessary.
This now works also if there is no "local" provider in the current
configuration.
-rw-r--r-- | server/db/sysdb.c | 366 |
1 files changed, 186 insertions, 180 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c index c07a07440..88d601189 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -744,19 +744,26 @@ void sysdb_operation_done(struct sysdb_handle *handle) /* =Initialization======================================================== */ +static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + 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, - struct sss_domain_info *domain, + const char *provider, const char *name, const char *base_path, char **_ldb_file) { char *ldb_file; /* special case for the local domain */ - if (strcasecmp(domain->provider, "local") == 0) { + if (strcasecmp(provider, "local") == 0) { ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE, base_path); } else { ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE, - base_path, domain->name); + base_path, name); } if (!ldb_file) { return ENOMEM; @@ -773,9 +780,10 @@ static int sysdb_get_db_file(TALLOC_CTX *mem_ctx, * finally stop indexing memberUid * upgrade version to 0.2 */ -static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) +static int sysdb_upgrade_01(TALLOC_CTX *mem_ctx, + struct ldb_context *ldb, + const char **ver) { - TALLOC_CTX *tmp_ctx; struct ldb_message_element *el; struct ldb_result *res; struct ldb_dn *basedn; @@ -788,17 +796,13 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) char *domain; int ret, i, j; - tmp_ctx = talloc_new(ctx); - if (!tmp_ctx) - return ENOMEM; - - basedn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb"); + basedn = ldb_dn_new(mem_ctx, ldb, "cn=sysdb"); if (!basedn) { ret = EIO; goto done; } - ret = ldb_search(ctx->ldb, tmp_ctx, &res, + ret = ldb_search(ldb, mem_ctx, &res, basedn, LDB_SCOPE_SUBTREE, attrs, filter); if (ret != LDB_SUCCESS) { @@ -806,7 +810,7 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) goto done; } - ret = ldb_transaction_start(ctx->ldb); + ret = ldb_transaction_start(ldb); if (ret != LDB_SUCCESS) { ret = EIO; goto done; @@ -821,7 +825,7 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) } /* create modification message */ - msg = ldb_msg_new(tmp_ctx); + msg = ldb_msg_new(mem_ctx); if (!msg) { ret = ENOMEM; goto done; @@ -842,15 +846,15 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) /* 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); + domain = talloc_strndup(mem_ctx, (const char *)val->data, val->length); if (!domain) { ret = ENOMEM; goto done; } for (j = 0; j < el->num_values; j++) { - mem_dn = sysdb_user_dn(ctx, tmp_ctx, domain, - (const char *)el->values[j].data); + mem_dn = ldb_dn_new_fmt(mem_ctx, ldb, SYSDB_TMPL_USER, + (const char *)el->values[j].data, domain); if (!mem_dn) { ret = ENOMEM; goto done; @@ -871,7 +875,7 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) } /* ok now we are ready to modify the entry */ - ret = ldb_modify(ctx->ldb, msg); + ret = ldb_modify(ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; @@ -881,12 +885,12 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) } /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); + msg = ldb_msg_new(mem_ctx); if (!msg) { ret = ENOMEM; goto done; } - msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb"); + msg->dn = ldb_dn_new(mem_ctx, ldb, "cn=sysdb"); if (!msg->dn) { ret = ENOMEM; goto done; @@ -903,93 +907,145 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver) goto done; } - ret = ldb_modify(ctx->ldb, msg); + ret = ldb_modify(ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } - talloc_zfree(tmp_ctx); ret = EOK; done: if (ret != EOK) { - ret = ldb_transaction_cancel(ctx->ldb); + ldb_transaction_cancel(ldb); } else { - ret = ldb_transaction_commit(ctx->ldb); - } - if (ret != LDB_SUCCESS) { - return EIO; + ret = ldb_transaction_commit(ldb); + if (ret != LDB_SUCCESS) { + return EIO; + } + + *ver = SYSDB_VERSION_0_2; } - *ver = SYSDB_VERSION_0_2; return ret; } -static int sysdb_upgrade_02(struct confdb_ctx *cdb, - struct tevent_context *ev, - struct sysdb_ctx *local, - struct sysdb_ctx_list *list) +static int sysdb_check_upgrade_02(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sss_domain_info *domains, + const char *db_path) { - TALLOC_CTX *tmp_ctx; + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_context *ldb; + char *ldb_file; struct sysdb_ctx *ctx; + struct sss_domain_info *dom; struct ldb_message_element *el; struct ldb_message *msg; struct ldb_result *res; - struct ldb_dn *basedn; - const char *version; - bool loc_trans = false; + struct ldb_dn *verdn; + const char *version = NULL; + bool do_02_upgrade = false; bool ctx_trans = false; - int ret, i, j; + int ret; - tmp_ctx = talloc_new(list); + tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return ENOMEM; } - /* first check local has the expected version for an upgrade */ + ret = sysdb_get_db_file(mem_ctx, + "local", "UPGRADE", + db_path, &ldb_file); + if (ret != EOK) { + goto exit; + } - basedn = ldb_dn_new(tmp_ctx, local->ldb, "cn=sysdb"); - if (!basedn) { + ldb = ldb_init(tmp_ctx, ev); + if (!ldb) { ret = EIO; - goto done; + goto exit; + } + + ret = ldb_set_debug(ldb, ldb_debug_messages, NULL); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto exit; + } + +#ifdef SYSDB_TEST + ldb_set_modules_dir(ldb, "./.libs"); +#endif + + ret = ldb_connect(ldb, ldb_file, 0, NULL); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto exit; + } + + verdn = ldb_dn_new(tmp_ctx, ldb, "cn=sysdb"); + if (!verdn) { + ret = EIO; + goto exit; } - ret = ldb_search(local->ldb, tmp_ctx, &res, - basedn, LDB_SCOPE_BASE, + ret = ldb_search(ldb, tmp_ctx, &res, + verdn, LDB_SCOPE_BASE, NULL, NULL); if (ret != LDB_SUCCESS) { ret = EIO; - goto done; + goto exit; } - if (res->count != 1) { + if (res->count > 1) { ret = EIO; - goto done; + goto exit; } - el = ldb_msg_find_element(res->msgs[0], "version"); - if (el) { - if (el->num_values != 1) { - ret = EINVAL; - goto done; - } - version = talloc_strndup(tmp_ctx, - (char *)(el->values[0].data), - el->values[0].length); - if (!version) { - ret = ENOMEM; - goto done; - } + 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(tmp_ctx, 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 (strcmp(version, SYSDB_VERSION_0_2) != 0) { - DEBUG(0,("Wrong DB version [%s]," - " expected [%s] for this upgrade!\n", - version, SYSDB_VERSION)); - ret = EINVAL; - goto done; } } - talloc_zfree(res); + + 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)); @@ -1001,49 +1057,60 @@ static int sysdb_upgrade_02(struct confdb_ctx *cdb, /* == Backup and reopen ldb == */ /* close */ - talloc_zfree(local->ldb); + talloc_zfree(ldb); /* backup*/ - ret = backup_file(local->ldb_file, 0); + ret = backup_file(ldb_file, 0); if (ret != EOK) { - return ret; + goto exit; } /* reopen */ - local->ldb = ldb_init(local, ev); - if (!local->ldb) { - return EIO; + ldb = ldb_init(tmp_ctx, ev); + if (!ldb) { + ret = EIO; + goto exit; } - ret = ldb_set_debug(local->ldb, ldb_debug_messages, NULL); + ret = ldb_set_debug(ldb, ldb_debug_messages, NULL); if (ret != LDB_SUCCESS) { - return EIO; + ret = EIO; + goto exit; } - ret = ldb_connect(local->ldb, local->ldb_file, 0, NULL); + ret = ldb_connect(ldb, ldb_file, 0, NULL); if (ret != LDB_SUCCESS) { - return EIO; + ret = EIO; + goto exit; } /* open a transaction */ - ret = ldb_transaction_start(local->ldb); + ret = ldb_transaction_start(ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); - return EIO; + ret = EIO; + goto exit; } - loc_trans = true; /* == Upgrade contents == */ - for (i = 0; i < list->num_dbs; i++) { + for (dom = domains; dom; dom = dom->next) { struct ldb_dn *domain_dn; struct ldb_dn *users_dn; struct ldb_dn *groups_dn; - - ctx = list->dbs[i]; + int i; /* skip local */ - if (list->dbs[i] == local) continue; + if (strcasecmp(dom->provider, "local") == 0) { + continue; + } + + /* create new dom db */ + ret = sysdb_domain_init_internal(tmp_ctx, ev, dom, + db_path, false, &ctx); + if (ret != EOK) { + goto done; + } ret = ldb_transaction_start(ctx->ldb); if (ret != LDB_SUCCESS) { @@ -1064,7 +1131,7 @@ static int sysdb_upgrade_02(struct confdb_ctx *cdb, goto done; } - ret = ldb_search(local->ldb, tmp_ctx, &res, + ret = ldb_search(ldb, tmp_ctx, &res, domain_dn, LDB_SCOPE_SUBTREE, NULL, NULL); if (ret != LDB_SUCCESS) { @@ -1085,11 +1152,11 @@ static int sysdb_upgrade_02(struct confdb_ctx *cdb, goto done; } - for (j = 0; j < res->count; j++) { + for (i = 0; i < res->count; i++) { struct ldb_dn *orig_dn; - msg = res->msgs[j]; + msg = res->msgs[i]; /* skip pre-created congtainers */ if ((ldb_dn_compare(msg->dn, domain_dn) == 0) || @@ -1117,38 +1184,38 @@ static int sysdb_upgrade_02(struct confdb_ctx *cdb, ret, ldb_errstring(ctx->ldb))); } - ret = ldb_delete(local->ldb, orig_dn); + 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(msg->dn), - ret, ldb_errstring(local->ldb))); + 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(local->ldb, groups_dn); + 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(msg->dn), - ret, ldb_errstring(local->ldb))); + ret, ldb_errstring(ldb))); } - ret = ldb_delete(local->ldb, users_dn); + 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(msg->dn), - ret, ldb_errstring(local->ldb))); + ret, ldb_errstring(ldb))); } - ret = ldb_delete(local->ldb, domain_dn); + 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(msg->dn), - ret, ldb_errstring(local->ldb))); + ret, ldb_errstring(ldb))); } ret = ldb_transaction_commit(ctx->ldb); @@ -1171,7 +1238,7 @@ static int sysdb_upgrade_02(struct confdb_ctx *cdb, ret = ENOMEM; goto done; } - msg->dn = ldb_dn_new(tmp_ctx, local->ldb, "cn=sysdb"); + msg->dn = ldb_dn_new(tmp_ctx, ldb, "cn=sysdb"); if (!msg->dn) { ret = ENOMEM; goto done; @@ -1188,19 +1255,18 @@ static int sysdb_upgrade_02(struct confdb_ctx *cdb, goto done; } - ret = ldb_modify(local->ldb, msg); + ret = ldb_modify(ldb, msg); if (ret != LDB_SUCCESS) { ret = sysdb_error_to_errno(ret); goto done; } - ret = ldb_transaction_commit(local->ldb); + ret = ldb_transaction_commit(ldb); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); ret = EIO; - goto done; + goto exit; } - loc_trans = false; ret = EOK; @@ -1212,13 +1278,13 @@ done: DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); } } - if (loc_trans) { - ret = ldb_transaction_cancel(local->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; } @@ -1431,8 +1497,7 @@ 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, - bool *need_02_upgrade) + struct sysdb_ctx **_ctx) { TALLOC_CTX *tmp_ctx = NULL; struct sysdb_ctx *ctx; @@ -1458,7 +1523,9 @@ static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, ctx->mpg = true; } - ret = sysdb_get_db_file(ctx, domain, db_path, &ctx->ldb_file); + ret = sysdb_get_db_file(ctx, domain->provider, + domain->name, db_path, + &ctx->ldb_file); if (ret != EOK) { return ret; } @@ -1537,37 +1604,6 @@ static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, DEBUG(4, ("Upgrading DB [%s] from version: %s\n", domain->name, version)); - if (strcmp(version, SYSDB_VERSION_0_1) == 0) { - /* convert database */ - ret = sysdb_upgrade_01(ctx, &version); - if (ret != EOK) goto done; - } - - if (strcmp(version, SYSDB_VERSION_0_2) == 0) { - /* if this is not local we have a big problem */ - if (strcasecmp(domain->provider, "local") != 0) { - DEBUG(0, ("Fatal: providers other than 'local'" - " shouldn't present v0.2, db corrupted?\n")); - ret = EFAULT; - goto done; - } - - /* need to convert database to split files */ - /* this need to be done later when all domains are set up */ - if (need_02_upgrade) { - *need_02_upgrade = true; - } else { - DEBUG(0, ("DB file seem to need an upgrade," - " but upgrade flag is not provided," - " db corrupted?\n")); - ret = EFAULT; - goto done; - } - - ret = EOK; - goto done; - } - if (strcmp(version, SYSDB_VERSION_0_3) == 0) { ret = sysdb_upgrade_03(ctx, &version); if (ret != EOK) { @@ -1704,8 +1740,6 @@ int sysdb_init(TALLOC_CTX *mem_ctx, struct sysdb_ctx_list *ctx_list; struct sss_domain_info *domains, *dom; struct sysdb_ctx *ctx; - bool upgrade_02 = false; - const char *version = NULL; int ret; if (!ev) return EINVAL; @@ -1732,6 +1766,16 @@ int sysdb_init(TALLOC_CTX *mem_ctx, return ret; } + if (allow_upgrade) { + /* check if we have an old sssd.ldb to upgrade */ + ret = sysdb_check_upgrade_02(ctx_list, ev, domains, + ctx_list->db_path); + if (ret != EOK) { + talloc_zfree(ctx_list); + return ret; + } + } + for (dom = domains; dom; dom = dom->next) { ctx_list->dbs = talloc_realloc(ctx_list, ctx_list->dbs, @@ -1744,8 +1788,7 @@ int sysdb_init(TALLOC_CTX *mem_ctx, ret = sysdb_domain_init_internal(ctx_list, ev, dom, ctx_list->db_path, - allow_upgrade, - &ctx, &upgrade_02); + allow_upgrade, &ctx); if (ret != EOK) { talloc_zfree(ctx_list); return ret; @@ -1760,43 +1803,6 @@ int sysdb_init(TALLOC_CTX *mem_ctx, return ENOENT; } - if (upgrade_02) { - ret = confdb_get_domain(cdb, "local", &dom); - if (ret != EOK) { - talloc_zfree(ctx_list); - return ret; - } - ret = sysdb_get_ctx_from_list(ctx_list, dom, &ctx); - if (ret != EOK) { - talloc_zfree(ctx_list); - return ret; - } - - ret = sysdb_upgrade_02(cdb, ev, ctx, ctx_list); - if (ret != EOK) { - DEBUG(0, ("FATAL: Upgrade from db version %s failed!\n", - SYSDB_VERSION_0_2)); - DEBUG(0, ("You may find a backup of the database here: %s\n", - DB_PATH)); - talloc_zfree(ctx_list); - return ret; - } - ret = sysdb_upgrade_03(ctx, &version); - if (ret != EOK) { - DEBUG(0, ("FATAL: Upgrade from db version %s failed!\n", - SYSDB_VERSION_0_3)); - talloc_zfree(ctx_list); - return ret; - }; - ret = sysdb_upgrade_04(ctx, &version); - if (ret != EOK) { - DEBUG(0, ("FATAL: Upgrade from db version %s failed!\n", - SYSDB_VERSION_0_4)); - talloc_zfree(ctx_list); - return ret; - }; - } - *_ctx_list = ctx_list; return EOK; @@ -1809,7 +1815,7 @@ int sysdb_domain_init(TALLOC_CTX *mem_ctx, struct sysdb_ctx **_ctx) { return sysdb_domain_init_internal(mem_ctx, ev, domain, - db_path, false, _ctx, NULL); + db_path, false, _ctx); } int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list, |