/* we got a DN without a GUID - go find the GUID */
int ret = dsdb_module_guid_by_dn(module, dn, &p->guid, parent);
if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb, "Unable to find GUID for DN %s\n",
- ldb_dn_get_linearized(dn));
+ char *dn_str = NULL;
+ dn_str = ldb_dn_get_extended_linearized(mem_ctx,
+ (dn), 1);
+ ldb_asprintf_errstring(ldb,
+ "Unable to find GUID for DN %s\n",
+ dn_str);
if (ret == LDB_ERR_NO_SUCH_OBJECT &&
LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE &&
ldb_attr_cmp(el->name, "member") == 0) {
"*",
NULL
};
- unsigned int i, el_count = 0;
+ static const struct ldb_val true_val = {
+ .data = discard_const_p(uint8_t, "TRUE"),
+ .length = 4
+ };
+
+ unsigned int i;
uint32_t dsdb_flags = 0;
struct replmd_private *replmd_private;
enum deletion_state deletion_state, next_deletion_state;
guid = samdb_result_guid(old_msg, "objectGUID");
if (deletion_state == OBJECT_NOT_DELETED) {
+ struct ldb_message_element *is_deleted_el;
ret = replmd_make_deleted_child_dn(tmp_ctx,
ldb,
return ret;
}
- ret = ldb_msg_add_string(msg, "isDeleted", "TRUE");
+ ret = ldb_msg_add_value(msg, "isDeleted", &true_val,
+ &is_deleted_el);
if (ret != LDB_SUCCESS) {
ldb_asprintf_errstring(ldb, __location__
": Failed to add isDeleted string to the msg");
talloc_free(tmp_ctx);
return ret;
}
- msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
+ is_deleted_el->flags = LDB_FLAG_MOD_REPLACE;
} else {
/*
* No matter what has happened with other renames etc, try again to
if (deletion_state == OBJECT_NOT_DELETED) {
struct ldb_dn *parent_dn = ldb_dn_get_parent(tmp_ctx, old_dn);
char *parent_dn_str = NULL;
+ struct ldb_message_element *p_el;
/* we need the storage form of the parent GUID */
ret = dsdb_module_search_dn(module, tmp_ctx, &parent_res,
talloc_free(tmp_ctx);
return ret;
}
- msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
+ p_el = ldb_msg_find_element(msg,
+ "lastKnownParent");
+ if (p_el == NULL) {
+ talloc_free(tmp_ctx);
+ return ldb_module_operr(module);
+ }
+ p_el->flags = LDB_FLAG_MOD_REPLACE;
if (next_deletion_state == OBJECT_DELETED) {
ret = ldb_msg_add_value(msg, "msDS-LastKnownRDN", rdn_value, NULL);
talloc_free(tmp_ctx);
return ret;
}
- msg->elements[el_count++].flags = LDB_FLAG_MOD_ADD;
+ p_el = ldb_msg_find_element(msg,
+ "msDS-LastKnownRDN");
+ if (p_el == NULL) {
+ talloc_free(tmp_ctx);
+ return ldb_module_operr(module);
+ }
+ p_el->flags = LDB_FLAG_MOD_ADD;
}
}
* not activated and what ever the forest level is.
*/
if (dsdb_attribute_by_lDAPDisplayName(schema, "isRecycled") != NULL) {
- ret = ldb_msg_add_string(msg, "isRecycled", "TRUE");
+ struct ldb_message_element *is_recycled_el;
+
+ ret = ldb_msg_add_value(msg, "isRecycled", &true_val,
+ &is_recycled_el);
if (ret != LDB_SUCCESS) {
DEBUG(0,(__location__ ": Failed to add isRecycled string to the msg\n"));
ldb_module_oom(module);
talloc_free(tmp_ctx);
return ret;
}
- msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
+ is_recycled_el->flags = LDB_FLAG_MOD_REPLACE;
}
replmd_private = talloc_get_type(ldb_module_get_private(module),
their current values. This has the effect of changing these
attributes to have been last updated by the current DC. This is
needed to ensure that renames performed as part of conflict
- resolution are propogated to other DCs
+ resolution are propagated to other DCs
*/
static int replmd_name_modify(struct replmd_replicated_request *ar,
struct ldb_request *req, struct ldb_dn *dn)
"Conflict adding object '%s' from incoming replication as we are read only for the partition. \n"
" - We must fail the operation until a master for this partition resolves the conflict",
ldb_dn_get_linearized(conflict_dn));
+ ret = LDB_ERR_OPERATIONS_ERROR;
goto failed;
}
* replication will stop with an error, but there is not much
* else we can do.
*/
+ if (ret == LDB_SUCCESS) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ }
return ldb_module_done(ar->req, NULL, NULL,
ret);
}
"Conflict adding object '%s' from incoming replication but we are read only for the partition. \n"
" - We must fail the operation until a master for this partition resolves the conflict",
ldb_dn_get_linearized(conflict_dn));
+ ret = LDB_ERR_OPERATIONS_ERROR;
goto failed;
}
ldb_errstring(ldb_module_get_ctx(ar->module))));
goto failed;
}
-failed:
+ talloc_free(tmp_ctx);
+ return ret;
+failed:
/*
* On failure make the caller get the error
* This means replication will stop with an error,
* LDB_ERR_ENTRY_ALREADY_EXISTS case this is exactly what is
* needed.
*/
+ if (ret == LDB_SUCCESS) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ }
talloc_free(tmp_ctx);
return ret;
return LDB_ERR_OPERATIONS_ERROR;
}
+ /*
+ * All attributes listed here must be dealt with in some way
+ * by replmd_process_linked_attribute() otherwise in the case
+ * of isDeleted: FALSE the modify will fail with:
+ *
+ * Failed to apply linked attribute change 'attribute 'isDeleted':
+ * invalid modify flags on
+ * 'CN=g1_1527570609273,CN=Users,DC=samba,DC=example,DC=com':
+ * 0x0'
+ *
+ * This is becaue isDeleted is a Boolean, so FALSE is a
+ * legitimate value (set by Samba's deletetest.py)
+ */
attrs[0] = attr->lDAPDisplayName;
attrs[1] = "isDeleted";
attrs[2] = "isRecycled";
* recycled and tombstone objects. We don't have to delete
* any existing link, that should have happened when the
* object deletion was replicated or initiated.
+ *
+ * This needs isDeleted and isRecycled to be included as
+ * attributes in the search and so in msg if set.
*/
replmd_deletion_state(module, msg, &deletion_state, NULL);
return LDB_SUCCESS;
}
+ /*
+ * Now that we know the deletion_state, remove the extra
+ * attributes added for that purpose. We need to do this
+ * otherwise in the case of isDeleted: FALSE the modify will
+ * fail with:
+ *
+ * Failed to apply linked attribute change 'attribute 'isDeleted':
+ * invalid modify flags on
+ * 'CN=g1_1527570609273,CN=Users,DC=samba,DC=example,DC=com':
+ * 0x0'
+ *
+ * This is becaue isDeleted is a Boolean, so FALSE is a
+ * legitimate value (set by Samba's deletetest.py)
+ */
+
+ ldb_msg_remove_attr(msg, "isDeleted");
+ ldb_msg_remove_attr(msg, "isRecycled");
+
old_el = ldb_msg_find_element(msg, attr->lDAPDisplayName);
if (old_el == NULL) {
ret = ldb_msg_add_empty(msg, attr->lDAPDisplayName, LDB_FLAG_MOD_REPLACE, &old_el);