From 3a59cbd0b7b9c5dd3c62ac1679876070c264d80f Mon Sep 17 00:00:00 2001 From: Michal Zidek Date: Wed, 15 Aug 2012 10:56:21 +0200 Subject: Unify usage of sysdb transactions (part 2). --- src/db/sysdb_idmap.c | 430 ++++++++++++++++++++++++++------------------------- 1 file changed, 217 insertions(+), 213 deletions(-) (limited to 'src/db/sysdb_idmap.c') diff --git a/src/db/sysdb_idmap.c b/src/db/sysdb_idmap.c index 94566d773..eca3d1bd6 100644 --- a/src/db/sysdb_idmap.c +++ b/src/db/sysdb_idmap.c @@ -53,221 +53,225 @@ sysdb_idmap_store_mapping(struct sysdb_ctx *sysdb, const char *dom_sid, id_t slice_num) { - errno_t ret, sret; - int lret; - bool in_transaction = false; - TALLOC_CTX *tmp_ctx; - struct ldb_dn *dn; - static const char *attrs[] = SYSDB_IDMAP_ATTRS; - size_t count; - struct ldb_message *update_msg; - struct ldb_message **msgs; - const char *old_name; - id_t old_slice; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) return ENOMEM; - - dn = sysdb_idmap_dn(tmp_ctx, sysdb, dom_sid); - if (!dn) { - ret = ENOMEM; - goto done; - } - - update_msg = ldb_msg_new(tmp_ctx); - if (!update_msg) { - ret = ENOMEM; - goto done; - } - update_msg->dn = dn; - - ret = sysdb_transaction_start(sysdb); - if (ret != EOK) goto done; - in_transaction = true; - - - /* Check for an existing mapping */ - ret = sysdb_search_entry(tmp_ctx, sysdb, dn, LDB_SCOPE_BASE, - NULL, attrs, &count, &msgs); - if (ret != EOK && ret != ENOENT) goto done; - - if (ret == EOK && count != 1) { - /* More than one reply for a base search? */ - ret = EIO; - goto done; - } else if (ret == ENOENT) { - /* Create a new mapping */ - DEBUG(SSSDBG_CONF_SETTINGS, - ("Adding new ID mapping [%s][%s][%lu]\n", - dom_name, dom_sid, (unsigned long)slice_num)); - - /* Add the objectClass */ - lret = ldb_msg_add_empty(update_msg, SYSDB_OBJECTCLASS, - LDB_FLAG_MOD_ADD, - NULL); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - lret = ldb_msg_add_string(update_msg, SYSDB_OBJECTCLASS, - SYSDB_IDMAP_MAPPING_OC); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - /* Add the domain objectSID */ - lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SID_ATTR, - LDB_FLAG_MOD_ADD, - NULL); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - lret = ldb_msg_add_string(update_msg, SYSDB_IDMAP_SID_ATTR, dom_sid); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - /* Add the domain name */ - lret = ldb_msg_add_empty(update_msg, SYSDB_NAME, - LDB_FLAG_MOD_ADD, - NULL); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - /* Add the slice number */ - lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SLICE_ATTR, - LDB_FLAG_MOD_ADD, - NULL); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - lret = ldb_msg_add_fmt(update_msg, SYSDB_IDMAP_SLICE_ATTR, - "%lu", (unsigned long)slice_num); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - lret = ldb_add(sysdb->ldb, update_msg); - if (lret != LDB_SUCCESS) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to add mapping: [%s]\n", - ldb_strerror(lret))); - ret = sysdb_error_to_errno(lret); - goto done; - } - } else { - /* Update the existing mapping */ - - /* Check whether the slice has changed - * This should never happen, and it's a recipe for - * disaster. We'll throw an error if it does. - */ - old_slice = ldb_msg_find_attr_as_int(msgs[0], - SYSDB_IDMAP_SLICE_ATTR, - -1); - if (old_slice == -1) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Could not identify original slice for SID [%s]\n", - dom_sid)); - ret = ENOENT; - goto done; - } - - if (slice_num != old_slice) { - DEBUG(SSSDBG_FATAL_FAILURE, - ("Detected attempt to change slice value for sid [%s] " - "This will break existing users. Refusing to perform.\n")); - ret = EINVAL; - goto done; - } - - /* Check whether the name has changed. This may happen - * if we're told the real name of a domain and want to - * replace the SID as placeholder. - */ - old_name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL); - if (!old_name) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Could not identify original domain name of SID [%s]\n", - dom_sid)); - ret = ENOENT; - goto done; - } - - if (strcmp(old_name, dom_name) == 0) { - /* There's nothing to be done. We don't need to - * make any changes here. Just return success. - */ - DEBUG(SSSDBG_TRACE_LIBS, - ("No changes needed, canceling transaction\n")); - ret = EOK; - goto done; - } else { - /* The name has changed. Replace it */ - DEBUG(SSSDBG_CONF_SETTINGS, - ("Changing domain name of SID [%s] from [%s] to [%s]\n", - dom_sid, old_name, dom_name)); - - /* Set the new name */ - lret = ldb_msg_add_empty(update_msg, SYSDB_NAME, - LDB_FLAG_MOD_REPLACE, - NULL); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - - lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name); - if (lret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(lret); - goto done; - } - } - - lret = ldb_modify(sysdb->ldb, update_msg); - if (lret != LDB_SUCCESS) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Failed to update mapping: [%s]\n", - ldb_strerror(lret))); - ret = sysdb_error_to_errno(lret); - goto done; - } - } - - ret = sysdb_transaction_commit(sysdb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Could not commit transaction: [%s]\n", strerror(ret))); - goto done; - } - in_transaction = false; + errno_t ret, sret; + int lret; + bool in_transaction = false; + TALLOC_CTX *tmp_ctx; + struct ldb_dn *dn; + static const char *attrs[] = SYSDB_IDMAP_ATTRS; + size_t count; + struct ldb_message *update_msg; + struct ldb_message **msgs; + const char *old_name; + id_t old_slice; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return ENOMEM; + + dn = sysdb_idmap_dn(tmp_ctx, sysdb, dom_sid); + if (!dn) { + ret = ENOMEM; + goto done; + } + + update_msg = ldb_msg_new(tmp_ctx); + if (!update_msg) { + ret = ENOMEM; + goto done; + } + update_msg->dn = dn; + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); + goto done; + } + + in_transaction = true; + + + /* Check for an existing mapping */ + ret = sysdb_search_entry(tmp_ctx, sysdb, dn, LDB_SCOPE_BASE, + NULL, attrs, &count, &msgs); + if (ret != EOK && ret != ENOENT) goto done; + + if (ret == EOK && count != 1) { + /* More than one reply for a base search? */ + ret = EIO; + goto done; + } else if (ret == ENOENT) { + /* Create a new mapping */ + DEBUG(SSSDBG_CONF_SETTINGS, + ("Adding new ID mapping [%s][%s][%lu]\n", + dom_name, dom_sid, (unsigned long)slice_num)); + + /* Add the objectClass */ + lret = ldb_msg_add_empty(update_msg, SYSDB_OBJECTCLASS, + LDB_FLAG_MOD_ADD, + NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + lret = ldb_msg_add_string(update_msg, SYSDB_OBJECTCLASS, + SYSDB_IDMAP_MAPPING_OC); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + /* Add the domain objectSID */ + lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SID_ATTR, + LDB_FLAG_MOD_ADD, + NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + lret = ldb_msg_add_string(update_msg, SYSDB_IDMAP_SID_ATTR, dom_sid); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + /* Add the domain name */ + lret = ldb_msg_add_empty(update_msg, SYSDB_NAME, + LDB_FLAG_MOD_ADD, + NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + /* Add the slice number */ + lret = ldb_msg_add_empty(update_msg, SYSDB_IDMAP_SLICE_ATTR, + LDB_FLAG_MOD_ADD, + NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + lret = ldb_msg_add_fmt(update_msg, SYSDB_IDMAP_SLICE_ATTR, + "%lu", (unsigned long)slice_num); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + lret = ldb_add(sysdb->ldb, update_msg); + if (lret != LDB_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Failed to add mapping: [%s]\n", + ldb_strerror(lret))); + ret = sysdb_error_to_errno(lret); + goto done; + } + } else { + /* Update the existing mapping */ + + /* Check whether the slice has changed + * This should never happen, and it's a recipe for + * disaster. We'll throw an error if it does. + */ + old_slice = ldb_msg_find_attr_as_int(msgs[0], + SYSDB_IDMAP_SLICE_ATTR, + -1); + if (old_slice == -1) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Could not identify original slice for SID [%s]\n", + dom_sid)); + ret = ENOENT; + goto done; + } + + if (slice_num != old_slice) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Detected attempt to change slice value for sid [%s] " + "This will break existing users. Refusing to perform.\n")); + ret = EINVAL; + goto done; + } + + /* Check whether the name has changed. This may happen + * if we're told the real name of a domain and want to + * replace the SID as placeholder. + */ + old_name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL); + if (!old_name) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Could not identify original domain name of SID [%s]\n", + dom_sid)); + ret = ENOENT; + goto done; + } + + if (strcmp(old_name, dom_name) == 0) { + /* There's nothing to be done. We don't need to + * make any changes here. Just return success. + */ + DEBUG(SSSDBG_TRACE_LIBS, + ("No changes needed, canceling transaction\n")); + ret = EOK; + goto done; + } else { + /* The name has changed. Replace it */ + DEBUG(SSSDBG_CONF_SETTINGS, + ("Changing domain name of SID [%s] from [%s] to [%s]\n", + dom_sid, old_name, dom_name)); + + /* Set the new name */ + lret = ldb_msg_add_empty(update_msg, SYSDB_NAME, + LDB_FLAG_MOD_REPLACE, + NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + lret = ldb_msg_add_string(update_msg, SYSDB_NAME, dom_name); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + } + + lret = ldb_modify(sysdb->ldb, update_msg); + if (lret != LDB_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Failed to update mapping: [%s]\n", + ldb_strerror(lret))); + ret = sysdb_error_to_errno(lret); + goto done; + } + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Could not commit transaction: [%s]\n", strerror(ret))); + goto done; + } + in_transaction = false; done: - if (in_transaction) { - sret = sysdb_transaction_cancel(sysdb); - if (sret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Could not cancel transaction\n")); - } - } - talloc_free(tmp_ctx); - return ret; + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Could not cancel transaction\n")); + } + } + talloc_free(tmp_ctx); + return ret; } errno_t -- cgit