]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9772 Allow objectClass edits that don't actually change them
authorOndřej Kuzník <ondra@mistotebe.net>
Thu, 13 Jan 2022 11:03:47 +0000 (11:03 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Tue, 18 Jan 2022 23:04:09 +0000 (23:04 +0000)
servers/slapd/bconfig.c

index 303be1b50e3cf57863bc7e0939a9d896ea69826b..3e6136fd8d4ba949b5b254dc6ab02f1cd97db91e 100644 (file)
@@ -6077,8 +6077,49 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
 
        for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
-               if (ml->sml_desc == slap_schema.si_ad_objectClass)
-                       return rc;
+               if (ml->sml_desc == slap_schema.si_ad_objectClass) {
+                       /* We'd be fine comparing the structural objectclass before and
+                        * after, but AUXILIARY ocs exist so we have to check them all */
+                       unsigned int i, j;
+
+                       if ( ml->sml_numvals != oc_at->a_numvals ) {
+                               snprintf( ca->cr_msg, sizeof(ca->cr_msg),
+                                       "objectclass modification disallowed" );
+                               return LDAP_UNWILLING_TO_PERFORM;
+                       }
+
+                       for ( i = 0; i < oc_at->a_numvals; i++ ) {
+                               ObjectClass *new_oc, *old_oc = oc_bvfind( &oc_at->a_vals[i] );
+                               int found = 0;
+
+                               if ( old_oc == NULL ) {
+                                       snprintf( ca->cr_msg, sizeof(ca->cr_msg),
+                                               "no objectClass named %s",
+                                               oc_at->a_vals[i].bv_val );
+                                       return LDAP_OBJECT_CLASS_VIOLATION;
+                               }
+                               for ( j = 0; j < ml->sml_numvals; j++ ) {
+                                       new_oc = oc_bvfind( &ml->sml_values[j] );
+                                       if ( new_oc == NULL ) {
+                                               snprintf( ca->cr_msg, sizeof(ca->cr_msg),
+                                                       "no objectClass named %s",
+                                                       ml->sml_values[j].bv_val );
+                                               return LDAP_OBJECT_CLASS_VIOLATION;
+                                       }
+
+                                       if ( old_oc == new_oc ) {
+                                               found = 1;
+                                               break;
+                                       }
+                               }
+
+                               if ( !found ) {
+                                       snprintf( ca->cr_msg, sizeof(ca->cr_msg),
+                                               "objectclass modification disallowed" );
+                                       return LDAP_UNWILLING_TO_PERFORM;
+                               }
+                       }
+               }
        }
 
        colst = count_ocs( oc_at, &nocs );