9991ea
From 706617eee0f735d2a49fd41f5c86e8b22bbf5434 Mon Sep 17 00:00:00 2001
9991ea
From: Alexander Bokovoy <abokovoy@redhat.com>
9991ea
Date: Mon, 20 Jan 2014 16:42:48 +0200
9991ea
Subject: [PATCH] ipasam: delete trusted child domains before removing the
9991ea
 trust
9991ea
9991ea
LDAP protocol doesn't allow deleting non-leaf entries. One needs to
9991ea
remove all leaves first before removing the tree node.
9991ea
9991ea
https://fedorahosted.org/freeipa/ticket/4126
9991ea
---
9991ea
 daemons/ipa-sam/ipa_sam.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
9991ea
 1 file changed, 44 insertions(+), 1 deletion(-)
9991ea
9991ea
diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
9991ea
index 674085d2a14c67359df16458dbbb098414a24d8b..1ca504db4e442c834ebe44d7e3503abafd6f9602 100644
9991ea
--- a/daemons/ipa-sam/ipa_sam.c
9991ea
+++ b/daemons/ipa-sam/ipa_sam.c
9991ea
@@ -2437,6 +2437,44 @@ done:
9991ea
 	return status;
9991ea
 }
9991ea
 
9991ea
+static int delete_subtree(struct ldapsam_privates *ldap_state, char* dn)
9991ea
+{
9991ea
+	LDAP *state = priv2ld(ldap_state);
9991ea
+	int rc;
9991ea
+	char *filter = NULL;
9991ea
+	int scope = LDAP_SCOPE_SUBTREE;
9991ea
+	LDAPMessage *result = NULL;
9991ea
+	LDAPMessage *entry = NULL;
9991ea
+	char *entry_dn = NULL;
9991ea
+
9991ea
+	/* use 'dn' for a temporary talloc context */
9991ea
+	filter = talloc_asprintf(dn, "(objectClass=*)");
9991ea
+	if (filter == NULL) {
9991ea
+		return LDAP_NO_MEMORY;
9991ea
+	}
9991ea
+
9991ea
+	rc = smbldap_search(ldap_state->smbldap_state, dn, scope, filter, NULL, 0, &result);
9991ea
+	TALLOC_FREE(filter);
9991ea
+
9991ea
+	if (result != NULL) {
9991ea
+		smbldap_talloc_autofree_ldapmsg(dn, result);
9991ea
+	}
9991ea
+
9991ea
+	for (entry = ldap_first_entry(state, result);
9991ea
+	     entry != NULL;
9991ea
+	     entry = ldap_next_entry(state, entry)) {
9991ea
+		entry_dn = get_dn(dn, state, entry);
9991ea
+		/* remove child entries */
9991ea
+		if ((entry_dn != NULL) && (strcmp(entry_dn, dn) != 0)) {
9991ea
+			rc = smbldap_delete(ldap_state->smbldap_state, entry_dn);
9991ea
+		}
9991ea
+	}
9991ea
+	rc = smbldap_delete(ldap_state->smbldap_state, dn);
9991ea
+
9991ea
+	/* caller will destroy dn */
9991ea
+	return rc;
9991ea
+}
9991ea
+
9991ea
 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
9991ea
 					   const char *domain)
9991ea
 {
9991ea
@@ -2444,7 +2482,7 @@ static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
9991ea
 	struct ldapsam_privates *ldap_state =
9991ea
 		(struct ldapsam_privates *)methods->private_data;
9991ea
 	LDAPMessage *entry = NULL;
9991ea
-	const char *dn;
9991ea
+	char *dn;
9991ea
 	const char *domain_name;
9991ea
 	TALLOC_CTX *tmp_ctx;
9991ea
 	NTSTATUS status;
9991ea
@@ -2490,6 +2528,11 @@ static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
9991ea
 	}
9991ea
 
9991ea
 	ret = smbldap_delete(ldap_state->smbldap_state, dn);
9991ea
+	if (ret == LDAP_NOT_ALLOWED_ON_NONLEAF) {
9991ea
+		/* delete_subtree will use 'dn' as temporary context too */
9991ea
+		ret = delete_subtree(ldap_state, dn);
9991ea
+	}
9991ea
+
9991ea
 	if (ret != LDAP_SUCCESS) {
9991ea
 		status = NT_STATUS_UNSUCCESSFUL;
9991ea
 		goto done;
9991ea
-- 
9991ea
1.8.4.2
9991ea