File 0012-backport-ConfigLDAPdel-callback-from-current-master.dif of Package openldap2

From e9c58d8eb653e2e1fa8d84f8631dcc3fa5965db2 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <ralf@openldap.org>
Date: Tue, 15 Mar 2011 16:57:41 +0000
Subject: backport ConfigLDAPdel callback from current master

bnc#704398

diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index 3354c09..309668e 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -6047,10 +6047,12 @@ config_back_delete( Operation *op, SlapReply *rs )
 			rs->sr_matched = last->ce_entry->e_name.bv_val;
 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
 	} else if ( ce->ce_kids ) {
-		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+		rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
 	} else if ( op->o_abandon ) {
 		rs->sr_err = SLAPD_ABANDON;
-	} else if ( ce->ce_type == Cft_Overlay || ce->ce_type == Cft_Database){
+	} else if ( ce->ce_type == Cft_Overlay ||
+			ce->ce_type == Cft_Database ||
+			ce->ce_type == Cft_Misc ){
 		char *iptr;
 		int count, ixold;
 
@@ -6058,7 +6060,46 @@ config_back_delete( Operation *op, SlapReply *rs )
 		
 		if ( ce->ce_type == Cft_Overlay ){
 			overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi );
-		} else { /* Cft_Database*/
+		} else if ( ce->ce_type == Cft_Misc ) {
+			/*
+			 * only Cft_Misc objects that have a co_lddel handler set in
+			 * the ConfigOCs struct can be deleted. This code also
+			 * assumes that the entry can be only have one objectclass
+			 * with co_type == Cft_Misc
+			 */
+			ConfigOCs co, *coptr;
+			Attribute *oc_at;
+			int i;
+
+			oc_at = attr_find( ce->ce_entry->e_attrs,
+					slap_schema.si_ad_objectClass );
+			if ( !oc_at ) {
+				rs->sr_err = LDAP_OTHER;
+				rs->sr_text = "objectclass not found";
+				ldap_pvt_thread_pool_resume( &connection_pool );
+				goto out;
+			}
+			for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) {
+				co.co_name = &oc_at->a_nvals[i];
+				coptr = avl_find( CfOcTree, &co, CfOc_cmp );
+				if ( coptr == NULL || coptr->co_type != Cft_Misc ) {
+					continue;
+				}
+				if ( ! coptr->co_lddel || coptr->co_lddel( ce, op ) ){
+					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+					if ( ! coptr->co_lddel ) {
+						rs->sr_text = "No delete handler found";
+					} else {
+						rs->sr_err = LDAP_OTHER;
+						/* FIXME: We should return a helpful error message
+						 * here */
+					}
+					ldap_pvt_thread_pool_resume( &connection_pool );
+					goto out;
+				}
+				break;
+			}
+		} else if (ce->ce_type == Cft_Database ) {
 			if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
 				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
 				rs->sr_text = "Cannot delete config or frontend database";
@@ -6128,10 +6169,10 @@ config_back_delete( Operation *op, SlapReply *rs )
 	} else {
 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
 	}
+out:
 #else
 	rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
 #endif /* SLAP_CONFIG_DELETE */
-out:
 	send_ldap_result( op, rs );
 	return rs->sr_err;
 }
diff --git a/servers/slapd/config.h b/servers/slapd/config.h
index 9c037d4..d79ae74 100644
--- a/servers/slapd/config.h
+++ b/servers/slapd/config.h
@@ -100,12 +100,21 @@ typedef int (ConfigLDAPadd)(
 typedef int (ConfigCfAdd)(
 	Operation *op, SlapReply *rs, Entry *parent, struct config_args_s *ca );
 
+#ifdef SLAP_CONFIG_DELETE
+/* Called when deleting a Cft_Misc Child object from cn=config */
+typedef int (ConfigLDAPdel)(
+	CfEntryInfo *ce, Operation *op );
+#endif
+
 typedef struct ConfigOCs {
 	const char *co_def;
 	ConfigType co_type;
 	ConfigTable *co_table;
 	ConfigLDAPadd *co_ldadd;
 	ConfigCfAdd *co_cfadd;
+#ifdef SLAP_CONFIG_DELETE
+	ConfigLDAPdel *co_lddel;
+#endif
 	ObjectClass *co_oc;
 	struct berval *co_name;
 } ConfigOCs;
-- 
1.7.3.4

openSUSE Build Service is sponsored by