*/
static int replmd_delete_remove_link(struct ldb_module *module,
const struct dsdb_schema *schema,
+ struct replmd_private *replmd_private,
struct ldb_dn *dn,
+ struct GUID *guid,
struct ldb_message_element *el,
const struct dsdb_attribute *sa,
struct ldb_request *parent)
for (i=0; i<el->num_values; i++) {
struct dsdb_dn *dsdb_dn;
- NTSTATUS status;
int ret;
- struct GUID guid2;
struct ldb_message *msg;
const struct dsdb_attribute *target_attr;
struct ldb_message_element *el2;
+ const char *dn_str;
struct ldb_val dn_val;
uint32_t dsdb_flags = 0;
+ const char *attrs[] = { NULL, NULL };
+ struct ldb_result *link_res;
+ struct ldb_message *link_msg;
+ struct ldb_message_element *link_el;
+ struct parsed_dn *link_dns;
+ struct parsed_dn *p = NULL, *unused = NULL;
if (dsdb_dn_is_deleted_val(&el->values[i])) {
continue;
return LDB_ERR_OPERATIONS_ERROR;
}
- status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &guid2, "GUID");
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
/* remove the link */
msg = ldb_msg_new(tmp_ctx);
if (!msg) {
if (target_attr == NULL) {
continue;
}
+ attrs[0] = target_attr->lDAPDisplayName;
- ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName, LDB_FLAG_MOD_DELETE, &el2);
+ ret = ldb_msg_add_empty(msg, target_attr->lDAPDisplayName,
+ LDB_FLAG_MOD_DELETE, &el2);
if (ret != LDB_SUCCESS) {
ldb_module_oom(module);
talloc_free(tmp_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- dn_val = data_blob_string_const(ldb_dn_get_linearized(dn));
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &link_res,
+ msg->dn, attrs,
+ DSDB_FLAG_NEXT_MODULE |
+ DSDB_SEARCH_SHOW_EXTENDED_DN,
+ parent);
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ link_msg = link_res->msgs[0];
+ link_el = ldb_msg_find_element(link_msg,
+ target_attr->lDAPDisplayName);
+ if (link_el == NULL) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ }
+
+ /*
+ * This call 'upgrades' the links in link_dns, but we
+ * do not commit the result back into the database, so
+ * this is safe to call in FL2000 or on databases that
+ * have been run at that level in the past.
+ */
+ ret = get_parsed_dns_trusted(module, replmd_private, tmp_ctx,
+ link_el, &link_dns,
+ target_attr->syntax->ldap_oid, parent);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = parsed_dn_find(ldb, link_dns, link_el->num_values,
+ guid, dn, &p, &unused,
+ target_attr->syntax->ldap_oid);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (p == NULL) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "Failed to find forward link on %s "
+ "as %s to remove backlink %s on %s",
+ ldb_dn_get_linearized(msg->dn),
+ target_attr->lDAPDisplayName,
+ sa->lDAPDisplayName,
+ ldb_dn_get_linearized(dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ }
+
+
+ /* This needs to get the Binary DN, by first searching */
+ dn_str = dsdb_dn_get_linearized(tmp_ctx,
+ p->dsdb_dn);
+ dn_val = data_blob_string_const(dn_str);
el2->values = &dn_val;
el2->num_values = 1;
};
unsigned int i, el_count = 0;
uint32_t dsdb_flags = 0;
+ struct replmd_private *replmd_private;
enum deletion_state deletion_state, next_deletion_state;
if (ldb_dn_is_special(req->op.del.dn)) {
}
}
- if (deletion_state == OBJECT_NOT_DELETED) {
- /* get the objects GUID from the search we just did */
- guid = samdb_result_guid(old_msg, "objectGUID");
+ /* get the objects GUID from the search we just did */
+ guid = samdb_result_guid(old_msg, "objectGUID");
+ if (deletion_state == OBJECT_NOT_DELETED) {
/* Add a formatted child */
retb = ldb_dn_add_child_fmt(new_dn, "%s=%s\\0ADEL:%s",
rdn_name,
msg->elements[el_count++].flags = LDB_FLAG_MOD_REPLACE;
}
+ replmd_private = talloc_get_type(ldb_module_get_private(module),
+ struct replmd_private);
/* work out which of the old attributes we will be removing */
for (i=0; i<old_msg->num_elements; i++) {
const struct dsdb_attribute *sa;
/* don't remove the rDN */
continue;
}
- if (sa->linkID && (sa->linkID & 1)) {
+ if (sa->linkID & 1) {
/*
we have a backlink in this object
that needs to be removed. We're not
modify to delete the corresponding
forward link
*/
- ret = replmd_delete_remove_link(module, schema, old_dn, el, sa, req);
+ ret = replmd_delete_remove_link(module, schema,
+ replmd_private,
+ old_dn, &guid,
+ el, sa, req);
if (ret != LDB_SUCCESS) {
const char *old_dn_str
= ldb_dn_get_linearized(old_dn);
directly
*/
continue;
- }
- if (!sa->linkID) {
+ } else if (sa->linkID == 0) {
if (ldb_attr_in_list(preserved_attrs, el->name)) {
continue;
}