summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Zeleny <jzeleny@redhat.com>2012-04-23 14:08:00 -0400
committerStephen Gallagher <sgallagh@redhat.com>2012-05-31 15:46:27 -0400
commitc193cdcb43bffc1eac1bde6dfb0311e033e0c12f (patch)
tree78a6f8c529856da769c894d6bd20e9ef95667d07
parenta475628466a532213669864de4d5ecead563464d (diff)
downloadsssd-c193cdcb43bffc1eac1bde6dfb0311e033e0c12f.tar.gz
sssd-c193cdcb43bffc1eac1bde6dfb0311e033e0c12f.tar.bz2
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.
-rw-r--r--src/db/sysdb.c7
-rw-r--r--src/db/sysdb_private.h4
-rw-r--r--src/db/sysdb_upgrade.c147
3 files changed, 157 insertions, 1 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 41c677d7..fd76f73c 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -1061,6 +1061,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
}
}
+ if (strcmp(version, SYSDB_VERSION_0_10) == 0) {
+ ret = sysdb_upgrade_10(sysdb, &version);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
/* The version should now match SYSDB_VERSION.
* If not, it means we didn't match any of the
* known older versions. The DB might be
diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
index a162cbba..0fb7316b 100644
--- a/src/db/sysdb_private.h
+++ b/src/db/sysdb_private.h
@@ -23,6 +23,7 @@
#ifndef __INT_SYS_DB_H__
#define __INT_SYS_DB_H__
+#define SYSDB_VERSION_0_11 "0.11"
#define SYSDB_VERSION_0_10 "0.10"
#define SYSDB_VERSION_0_9 "0.9"
#define SYSDB_VERSION_0_8 "0.8"
@@ -34,7 +35,7 @@
#define SYSDB_VERSION_0_2 "0.2"
#define SYSDB_VERSION_0_1 "0.1"
-#define SYSDB_VERSION SYSDB_VERSION_0_10
+#define SYSDB_VERSION SYSDB_VERSION_0_11
#define SYSDB_BASE_LDIF \
"dn: @ATTRIBUTES\n" \
@@ -104,6 +105,7 @@ int sysdb_upgrade_06(struct sysdb_ctx *sysdb, const char **ver);
int sysdb_upgrade_07(struct sysdb_ctx *sysdb, const char **ver);
int sysdb_upgrade_08(struct sysdb_ctx *sysdb, const char **ver);
int sysdb_upgrade_09(struct sysdb_ctx *sysdb, const char **ver);
+int sysdb_upgrade_10(struct sysdb_ctx *sysdb, const char **ver);
int add_string(struct ldb_message *msg, int flags,
const char *attr, const char *value);
diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
index 4fe6afb3..b2dd7daf 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;
+}