diff options
author | Jan Zeleny <jzeleny@redhat.com> | 2012-04-23 14:08:00 -0400 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-05-31 15:46:27 -0400 |
commit | c193cdcb43bffc1eac1bde6dfb0311e033e0c12f (patch) | |
tree | 78a6f8c529856da769c894d6bd20e9ef95667d07 /src/db/sysdb_upgrade.c | |
parent | a475628466a532213669864de4d5ecead563464d (diff) | |
download | sssd-c193cdcb43bffc1eac1bde6dfb0311e033e0c12f.tar.gz sssd-c193cdcb43bffc1eac1bde6dfb0311e033e0c12f.tar.xz sssd-c193cdcb43bffc1eac1bde6dfb0311e033e0c12f.zip |
Ghost members - sysdb upgrade routine
It is remotely possible to have sysdb in an inconsistent state that
might need upgrade. Consider scenario when user asks for group
information. Some fake users are added as a part of this operation.
Before users can be fully resolved and stored properly, SSSD is shut
down and upgrade is performed.
In this case we need to go over all fake user records (uidNumber=0) and
replace each of them with ghost record in all group objects that are stated in
its memberof attribute.
Diffstat (limited to 'src/db/sysdb_upgrade.c')
-rw-r--r-- | src/db/sysdb_upgrade.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c index 4fe6afb3e..b2dd7dafd 100644 --- a/src/db/sysdb_upgrade.c +++ b/src/db/sysdb_upgrade.c @@ -1169,3 +1169,150 @@ done: talloc_free(tmp_ctx); return ret; } + +int sysdb_upgrade_10(struct sysdb_ctx *sysdb, const char **ver) +{ + + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_result *res; + struct ldb_message *msg; + struct ldb_message *user; + struct ldb_message_element *memberof_el; + const char *name; + struct ldb_dn *basedn; + const char *filter = "(&(objectClass=user)(!(uidNumber=*))(memberOf=*))"; + const char *attrs[] = { "name", "memberof", NULL }; + int i, j; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_USER_BASE, + sysdb->domain->name); + if (basedn == NULL) { + ret = EIO; + goto done; + } + + DEBUG(SSSDBG_CRIT_FAILURE, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_11)); + + ret = ldb_transaction_start(sysdb->ldb); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + ret = ldb_search(sysdb->ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE, + attrs, "%s", filter); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + for (i = 0; i < res->count; i++) { + user = res->msgs[i]; + memberof_el = ldb_msg_find_element(user, "memberof"); + name = ldb_msg_find_attr_as_string(user, "name", NULL); + if (name == NULL) { + ret = EIO; + goto done; + } + + for (j = 0; j < memberof_el->num_values; j++) { + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_from_ldb_val(tmp_ctx, sysdb->ldb, &memberof_el->values[j]); + if (msg->dn == NULL) { + ret = ENOMEM; + goto done; + } + + if (!ldb_dn_validate(msg->dn)) { + DEBUG(SSSDBG_MINOR_FAILURE, ("DN validation failed during " + "upgrade: [%s]\n", + memberof_el->values[j].data)); + talloc_zfree(msg); + continue; + } + + ret = ldb_msg_add_empty(msg, "ghost", LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "ghost", name); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_empty(msg, "member", LDB_FLAG_MOD_DELETE, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "member", ldb_dn_get_linearized(user->dn)); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_modify(sysdb->ldb, msg); + talloc_zfree(msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + } + + ret = ldb_delete(sysdb->ldb, user->dn); + 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_11); + 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_11, ver); + talloc_free(tmp_ctx); + return ret; +} |