From 2443e986d1bee1266412ee324b821ab356301e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= Date: Thu, 13 Jan 2022 11:03:47 +0000 Subject: [PATCH] ITS#9772 Allow objectClass edits that don't actually change them --- servers/slapd/bconfig.c | 45 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 3b1a4b3bc..7b6840be3 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -5895,8 +5895,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 ); -- 2.33.0