From e9c58d8eb653e2e1fa8d84f8631dcc3fa5965db2 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp 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