From: Pierangelo Masarati Date: Wed, 4 Feb 2009 22:36:49 +0000 (+0000) Subject: fix structuralObjectClass modification (glue, ITS#5921; w/ relax, ITS#5792) X-Git-Tag: ACLCHECK_0~887 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=260fd357df7df4a47eea79f552f52e0affc575ef;p=openldap fix structuralObjectClass modification (glue, ITS#5921; w/ relax, ITS#5792) --- diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 30074f93f3..921c41d573 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -94,7 +94,7 @@ txnReturn: /* check entry's schema */ rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL, - get_relax(op), 1, &rs->sr_text, textbuf, textlen ); + get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": entry failed schema check: " diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index 088accdcca..c6e3cd03f6 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -27,6 +27,44 @@ static struct berval scbva[] = { BER_BVNULL }; +static void +bdb_modify_idxflags( + Operation *op, + AttributeDescription *desc, + int got_delete, + Attribute *newattrs, + Attribute *oldattrs ) +{ + struct berval ix_at; + AttrInfo *ai; + + /* check if modified attribute was indexed + * but not in case of NOOP... */ + ai = bdb_index_mask( op->o_bd, desc, &ix_at ); + if ( ai ) { + if ( got_delete ) { + Attribute *ap; + struct berval ix2; + + ap = attr_find( oldattrs, desc ); + if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL; + + /* Find all other attrs that index to same slot */ + for ( ap = newattrs; ap; ap = ap->a_next ) { + ai = bdb_index_mask( op->o_bd, ap->a_desc, &ix2 ); + if ( ai && ix2.bv_val == ix_at.bv_val ) + ap->a_flags |= SLAP_ATTR_IXADD; + } + + } else { + Attribute *ap; + + ap = attr_find( newattrs, desc ); + if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD; + } + } +} + int bdb_modify_internal( Operation *op, DB_TXN *tid, @@ -43,7 +81,6 @@ int bdb_modify_internal( Attribute *ap; int glue_attr_delete = 0; int got_delete; - AttrInfo *ai; Debug( LDAP_DEBUG_TRACE, "bdb_modify_internal: 0x%08lx: %s\n", e->e_id, e->e_dn, 0); @@ -89,7 +126,6 @@ int bdb_modify_internal( } for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { - struct berval ix_at; mod = &ml->sml_mod; got_delete = 0; @@ -202,31 +238,17 @@ int bdb_modify_internal( if ( glue_attr_delete ) e->e_ocflags = 0; + /* check if modified attribute was indexed * but not in case of NOOP... */ - ai = bdb_index_mask( op->o_bd, mod->sm_desc, &ix_at ); - if ( ai && !op->o_noop ) { - if ( got_delete ) { - struct berval ix2; - - ap = attr_find( save_attrs, mod->sm_desc ); - if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL; - - /* Find all other attrs that index to same slot */ - for ( ap = e->e_attrs; ap; ap=ap->a_next ) { - ai = bdb_index_mask( op->o_bd, ap->a_desc, &ix2 ); - if ( ai && ix2.bv_val == ix_at.bv_val ) - ap->a_flags |= SLAP_ATTR_IXADD; - } - } else { - ap = attr_find( e->e_attrs, mod->sm_desc ); - if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD; - } + if ( !op->o_noop ) { + bdb_modify_idxflags( op, mod->sm_desc, got_delete, e->e_attrs, save_attrs ); } } /* check that the entry still obeys the schema */ - rc = entry_schema_check( op, e, save_attrs, get_relax(op), 0, + ap = NULL; + rc = entry_schema_check( op, e, save_attrs, get_relax(op), 0, &ap, text, textbuf, textlen ); if ( rc != LDAP_SUCCESS || op->o_noop ) { attrs_free( e->e_attrs ); @@ -246,6 +268,15 @@ int bdb_modify_internal( return rc; } + /* structuralObjectClass modified! */ + if ( ap ) { + assert( ap->a_desc == slap_schema.si_ad_structuralObjectClass ); + if ( !op->o_noop ) { + bdb_modify_idxflags( op, slap_schema.si_ad_structuralObjectClass, + 1, e->e_attrs, save_attrs ); + } + } + /* update the indices of the modified attributes */ /* start with deleting the old index entries */ diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index 1fb5e52685..4625af8c8d 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -1065,7 +1065,7 @@ apply_modify_to_entry( entry->e_ocflags = 0; } /* check that the entry still obeys the schema */ - rc = entry_schema_check( op, entry, NULL, 0, 0, + rc = entry_schema_check( op, entry, NULL, 0, 0, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); } @@ -1230,7 +1230,7 @@ ldif_back_add( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, "ldif_back_add: \"%s\"\n", e->e_dn, 0, 0 ); - rc = entry_schema_check( op, e, NULL, 0, 1, + rc = entry_schema_check( op, e, NULL, 0, 1, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rc != LDAP_SUCCESS ) goto send_res; diff --git a/servers/slapd/back-monitor/log.c b/servers/slapd/back-monitor/log.c index 70c45a2ff1..d772fd260f 100644 --- a/servers/slapd/back-monitor/log.c +++ b/servers/slapd/back-monitor/log.c @@ -181,7 +181,7 @@ monitor_subsys_log_modify( } /* check that the entry still obeys the schema */ - rc = entry_schema_check( op, e, save_attrs, 0, 0, + rc = entry_schema_check( op, e, save_attrs, 0, 0, NULL, &text, textbuf, sizeof( textbuf ) ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = rc; diff --git a/servers/slapd/back-ndb/add.cpp b/servers/slapd/back-ndb/add.cpp index 91e32d9444..4efdbcd14f 100644 --- a/servers/slapd/back-ndb/add.cpp +++ b/servers/slapd/back-ndb/add.cpp @@ -54,7 +54,7 @@ ndb_back_add(Operation *op, SlapReply *rs ) /* check entry's schema */ rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL, - get_relax(op), 1, &rs->sr_text, textbuf, textlen ); + get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_add) ": entry failed schema check: " diff --git a/servers/slapd/back-ndb/modify.cpp b/servers/slapd/back-ndb/modify.cpp index 275873c362..3733069c98 100644 --- a/servers/slapd/back-ndb/modify.cpp +++ b/servers/slapd/back-ndb/modify.cpp @@ -322,7 +322,7 @@ int ndb_modify_internal( } /* check that the entry still obeys the schema */ - rc = entry_schema_check( op, NA->e, NULL, get_relax(op), 0, + rc = entry_schema_check( op, NA->e, NULL, get_relax(op), 0, NULL, text, textbuf, textlen ); if ( rc != LDAP_SUCCESS || op->o_noop ) { if ( rc != LDAP_SUCCESS ) { diff --git a/servers/slapd/back-sql/add.c b/servers/slapd/back-sql/add.c index 546441e2e9..ae88f76e49 100644 --- a/servers/slapd/back-sql/add.c +++ b/servers/slapd/back-sql/add.c @@ -962,7 +962,7 @@ backsql_add( Operation *op, SlapReply *rs ) if ( BACKSQL_CHECK_SCHEMA( bi ) ) { char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; - rs->sr_err = entry_schema_check( op, op->ora_e, NULL, 0, 1, + rs->sr_err = entry_schema_check( op, op->ora_e, NULL, 0, 1, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " diff --git a/servers/slapd/back-sql/modify.c b/servers/slapd/back-sql/modify.c index f7cfe44f7a..941bc37548 100644 --- a/servers/slapd/back-sql/modify.c +++ b/servers/slapd/back-sql/modify.c @@ -152,7 +152,7 @@ backsql_modify( Operation *op, SlapReply *rs ) goto do_transact; } - rs->sr_err = entry_schema_check( op, &m, NULL, 0, 0, + rs->sr_err = entry_schema_check( op, &m, NULL, 0, 0, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify(\"%s\"): " diff --git a/servers/slapd/back-sql/modrdn.c b/servers/slapd/back-sql/modrdn.c index 0f273e145a..fafd98ee54 100644 --- a/servers/slapd/back-sql/modrdn.c +++ b/servers/slapd/back-sql/modrdn.c @@ -455,7 +455,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) e_id = bsi.bsi_base_id; - rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0, + rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): " diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index f4b15de936..1a64b230ab 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -4695,7 +4695,7 @@ config_back_add( Operation *op, SlapReply *rs ) { char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; - rs->sr_err = entry_schema_check(op, op->ora_e, NULL, 0, 1, + rs->sr_err = entry_schema_check(op, op->ora_e, NULL, 0, 1, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) goto out; @@ -4941,7 +4941,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs, if ( rc == LDAP_SUCCESS) { /* check that the entry still obeys the schema */ - rc = entry_schema_check(op, e, NULL, 0, 0, + rc = entry_schema_check(op, e, NULL, 0, 0, NULL, &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) ); } if ( rc ) goto out_noop; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 5837bb50f2..6e8c0fe47c 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -1643,6 +1643,7 @@ LDAP_SLAPD_F( int ) entry_schema_check( Attribute *attrs, int manage, int add, + Attribute **socp, const char** text, char *textbuf, size_t textlen ); diff --git a/servers/slapd/schema_check.c b/servers/slapd/schema_check.c index a49517f7c5..b466613c47 100644 --- a/servers/slapd/schema_check.c +++ b/servers/slapd/schema_check.c @@ -49,6 +49,7 @@ entry_schema_check( Attribute *oldattrs, int manage, int add, + Attribute **socp, const char** text, char *textbuf, size_t textlen ) { @@ -212,15 +213,28 @@ got_soc: rc = LDAP_OBJECT_CLASS_VIOLATION; goto done; - } else if ( sc != slap_schema.si_oc_glue && sc != oc ) { - snprintf( textbuf, textlen, - "structural object class modification " - "from '%s' to '%s' not allowed", - asc->a_vals[0].bv_val, oc->soc_cname.bv_val ); - rc = LDAP_NO_OBJECT_CLASS_MODS; - goto done; - } else if ( sc == slap_schema.si_oc_glue ) { + } else if ( sc != oc ) { + if ( !manage && sc != slap_schema.si_oc_glue ) { + snprintf( textbuf, textlen, + "structural object class modification " + "from '%s' to '%s' not allowed", + asc->a_vals[0].bv_val, oc->soc_cname.bv_val ); + rc = LDAP_NO_OBJECT_CLASS_MODS; + goto done; + } + + assert( asc->a_vals != NULL ); + assert( !BER_BVISNULL( &asc->a_vals[0] ) ); + assert( BER_BVISNULL( &asc->a_vals[1] ) ); + assert( asc->a_nvals == asc->a_vals ); + + /* draft-zeilenga-ldap-relax: automatically modify + * structuralObjectClass if changed with relax */ sc = oc; + ber_bvreplace( &asc->a_vals[ 0 ], &sc->soc_cname ); + if ( socp ) { + *socp = asc; + } } /* naming check */ diff --git a/servers/slapd/slapadd.c b/servers/slapd/slapadd.c index a0bf97e3ee..fd9558e523 100644 --- a/servers/slapd/slapadd.c +++ b/servers/slapd/slapadd.c @@ -192,7 +192,7 @@ slapadd( int argc, char **argv ) op->o_bd = be; if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) { - rc = entry_schema_check( op, e, NULL, manage, 1, + rc = entry_schema_check( op, e, NULL, manage, 1, NULL, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c index ecf351d90d..e6613e4d12 100644 --- a/servers/slapd/slapi/slapi_utils.c +++ b/servers/slapd/slapi/slapi_utils.c @@ -3117,7 +3117,7 @@ int slapi_entry_schema_check( Slapi_PBlock *pb, Slapi_Entry *e ) pb->pb_op->o_bd = select_backend( &e->e_nname, 0 ); if ( pb->pb_op->o_bd != NULL ) { - rc = entry_schema_check( pb->pb_op, e, NULL, 0, 0, + rc = entry_schema_check( pb->pb_op, e, NULL, 0, 0, NULL, &text, textbuf, textlen ); } pb->pb_op->o_bd = be_orig;