]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#10064 Allow renaming of Cft_Misc entries
authorOndřej Kuzník <ondra@mistotebe.net>
Tue, 21 Feb 2023 13:38:32 +0000 (13:38 +0000)
committerOndřej Kuzník <ondra@mistotebe.net>
Tue, 6 Jun 2023 10:46:17 +0000 (11:46 +0100)
servers/slapd/bconfig.c
servers/slapd/slap-config.h
servers/slapd/slap.h

index 51e25d967cec0743f0ccb8b5833a113bf60d2bb0..bf3969d6a6e3ae7e719f57692f2a7087fd22b841 100644 (file)
@@ -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:
index 2e9a009db71eeadfb78a758eaae35d4e6046b608..2ee09d942f60c0bd41aad083425e27576949d419 100644 (file)
@@ -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;
index 4a7a3f06ba50a3f66bfed3a78e94fc799428e06d..47eb588049b0dc18bcc1181120fdc852232f2a85 100644 (file)
@@ -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