Blob Blame History Raw
From 706617eee0f735d2a49fd41f5c86e8b22bbf5434 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Mon, 20 Jan 2014 16:42:48 +0200
Subject: [PATCH] ipasam: delete trusted child domains before removing the
 trust

LDAP protocol doesn't allow deleting non-leaf entries. One needs to
remove all leaves first before removing the tree node.

https://fedorahosted.org/freeipa/ticket/4126
---
 daemons/ipa-sam/ipa_sam.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index 674085d2a14c67359df16458dbbb098414a24d8b..1ca504db4e442c834ebe44d7e3503abafd6f9602 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -2437,6 +2437,44 @@ done:
 	return status;
 }
 
+static int delete_subtree(struct ldapsam_privates *ldap_state, char* dn)
+{
+	LDAP *state = priv2ld(ldap_state);
+	int rc;
+	char *filter = NULL;
+	int scope = LDAP_SCOPE_SUBTREE;
+	LDAPMessage *result = NULL;
+	LDAPMessage *entry = NULL;
+	char *entry_dn = NULL;
+
+	/* use 'dn' for a temporary talloc context */
+	filter = talloc_asprintf(dn, "(objectClass=*)");
+	if (filter == NULL) {
+		return LDAP_NO_MEMORY;
+	}
+
+	rc = smbldap_search(ldap_state->smbldap_state, dn, scope, filter, NULL, 0, &result);
+	TALLOC_FREE(filter);
+
+	if (result != NULL) {
+		smbldap_talloc_autofree_ldapmsg(dn, result);
+	}
+
+	for (entry = ldap_first_entry(state, result);
+	     entry != NULL;
+	     entry = ldap_next_entry(state, entry)) {
+		entry_dn = get_dn(dn, state, entry);
+		/* remove child entries */
+		if ((entry_dn != NULL) && (strcmp(entry_dn, dn) != 0)) {
+			rc = smbldap_delete(ldap_state->smbldap_state, entry_dn);
+		}
+	}
+	rc = smbldap_delete(ldap_state->smbldap_state, dn);
+
+	/* caller will destroy dn */
+	return rc;
+}
+
 static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
 					   const char *domain)
 {
@@ -2444,7 +2482,7 @@ static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
 	struct ldapsam_privates *ldap_state =
 		(struct ldapsam_privates *)methods->private_data;
 	LDAPMessage *entry = NULL;
-	const char *dn;
+	char *dn;
 	const char *domain_name;
 	TALLOC_CTX *tmp_ctx;
 	NTSTATUS status;
@@ -2490,6 +2528,11 @@ static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
 	}
 
 	ret = smbldap_delete(ldap_state->smbldap_state, dn);
+	if (ret == LDAP_NOT_ALLOWED_ON_NONLEAF) {
+		/* delete_subtree will use 'dn' as temporary context too */
+		ret = delete_subtree(ldap_state, dn);
+	}
+
 	if (ret != LDAP_SUCCESS) {
 		status = NT_STATUS_UNSUCCESSFUL;
 		goto done;
-- 
1.8.4.2