From f635f9e6d86da0f6d171b25bb1b4144c2c4c9721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= Date: Tue, 21 Feb 2023 13:38:32 +0000 Subject: [PATCH] ITS#10064 Allow renaming of Cft_Misc entries --- servers/slapd/bconfig.c | 61 ++++++++++++++++++++++++++++++++----- servers/slapd/slap-config.h | 9 ++++++ servers/slapd/slap.h | 1 + 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 51e25d967c..bf3969d6a6 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -5471,7 +5471,8 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, goto done_noop; } if ( renum && *renum && coptr->co_type != Cft_Database && - coptr->co_type != Cft_Overlay ) + coptr->co_type != Cft_Overlay && + ( coptr->co_type != Cft_Misc || !coptr->co_ldmove ) ) { snprintf( ca->cr_msg, sizeof( ca->cr_msg ), "operation requires sibling renumbering" ); @@ -6467,8 +6468,9 @@ config_back_modrdn( Operation *op, SlapReply *rs ) /* Current behavior, subject to change as needed: * - * For backends and overlays, we only allow renumbering. * For schema, we allow renaming with the same number. + * For backends, overlays, we only allow renumbering. + * For misc we let the co_ldmove handler decide. * Otherwise, the op is not allowed. */ @@ -6493,8 +6495,8 @@ config_back_modrdn( Operation *op, SlapReply *rs ) rs->sr_text = "schema reordering not supported"; goto out; } - } else if ( ce->ce_type == Cft_Database || - ce->ce_type == Cft_Overlay ) { + } else if ( ce->ce_type >= Cft_Database && + ce->ce_type <= Cft_Misc ) { char *ptr1, *ptr2, *iptr1, *iptr2; int len1, len2; @@ -6517,8 +6519,9 @@ config_back_modrdn( Operation *op, SlapReply *rs ) len1 = ptr1 - rdn.bv_val; len2 = ptr2 - op->orr_newrdn.bv_val; - if ( rdn.bv_len - len1 != op->orr_newrdn.bv_len - len2 || - strncmp( ptr1, ptr2, rdn.bv_len - len1 )) { + if ( ce->ce_type != Cft_Misc && ( + rdn.bv_len - len1 != op->orr_newrdn.bv_len - len2 || + strncmp( ptr1, ptr2, rdn.bv_len - len1 ) ) ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "changing database/overlay type not allowed"; goto out; @@ -6631,7 +6634,50 @@ config_back_modrdn( Operation *op, SlapReply *rs ) backend_db_move( ce->ce_be, ixnew ); else if ( ce->ce_type == Cft_Overlay ) overlay_move( ce->ce_be, (slap_overinst *)ce->ce_bi, ixnew ); - + else if ( ce->ce_type == Cft_Misc ) { +#ifdef SLAP_CONFIG_RENAME + /* + * 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; + + 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"; + goto out2; + } + for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) { + co.co_name = &oc_at->a_nvals[i]; + coptr = ldap_avl_find( CfOcTree, &co, CfOc_cmp ); + if ( coptr == NULL || coptr->co_type != Cft_Misc ) { + continue; + } + if ( !coptr->co_ldmove || + coptr->co_ldmove( ce, op, rs, ixold, ixnew ) ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + if ( ! coptr->co_ldmove ) { + rs->sr_text = "No rename handler found"; + } else { + rs->sr_err = LDAP_OTHER; + /* FIXME: We should return a helpful error message + * here, hope the co_ldmove handler took care of it */ + } + goto out2; + } + break; + } +#else + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + goto out2; +#endif /* SLAP_CONFIG_RENAME */ + } + if ( ixold < ixnew ) { rs->sr_err = config_rename_del( op, rs, ce, ceold, ixold, cfb->cb_use_ldif ); @@ -6656,6 +6702,7 @@ config_back_modrdn( Operation *op, SlapReply *rs ) } } +out2:; ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock ); out: diff --git a/servers/slapd/slap-config.h b/servers/slapd/slap-config.h index 2e9a009db7..2ee09d942f 100644 --- a/servers/slapd/slap-config.h +++ b/servers/slapd/slap-config.h @@ -122,6 +122,12 @@ typedef int (ConfigCfAdd)( /* Called when deleting a Cft_Misc Child object from cn=config */ typedef int (ConfigLDAPdel)( CfEntryInfo *ce, Operation *op ); + +#ifdef SLAP_CONFIG_RENAME +/* Called when attempting to move a Cft_Misc object in cn=config */ +typedef int (ConfigLDAPmove)( + CfEntryInfo *ce, Operation *op, SlapReply *rs, int ixold, int ixnew ); +#endif #endif typedef struct ConfigOCs { @@ -132,6 +138,9 @@ typedef struct ConfigOCs { ConfigCfAdd *co_cfadd; #ifdef SLAP_CONFIG_DELETE ConfigLDAPdel *co_lddel; +#ifdef SLAP_CONFIG_RENAME + ConfigLDAPmove *co_ldmove; +#endif #endif ObjectClass *co_oc; struct berval *co_name; diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 4a7a3f06ba..47eb588049 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -71,6 +71,7 @@ LDAP_BEGIN_DECL #endif #define SLAP_CONFIG_DELETE +#define SLAP_CONFIG_RENAME #define SLAP_AUXPROP_DONTUSECOPY #define LDAP_DYNAMIC_OBJECTS #define SLAP_CONTROL_X_TREE_DELETE LDAP_CONTROL_X_TREE_DELETE