Example #1
0
int is_object_subclass(
	ObjectClass *sup,
	ObjectClass *sub )
{
	int i;

	if( sub == NULL || sup == NULL ) return 0;

#if 0
	Debug( LDAP_DEBUG_TRACE, "is_object_subclass(%s,%s) %d\n",
		sup->soc_oid, sub->soc_oid, sup == sub );
#endif

	if ( sup == sub ) {
		return 1;
	}

	if ( sub->soc_sups == NULL ) {
		return 0;
	}

	for ( i = 0; sub->soc_sups[i] != NULL; i++ ) {
		if ( is_object_subclass( sup, sub->soc_sups[i] ) ) {
			return 1;
		}
	}

	return 0;
}
static int
objectSubClassMatch(
	int *matchp,
	slap_mask_t flags,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	struct berval *a = (struct berval *) assertedValue;
	ObjectClass *oc = oc_bvfind( value );
	ObjectClass *asserted = oc_bvfind( a );

	if( asserted == NULL ) {
		if( OID_LEADCHAR( *a->bv_val ) ) {
			/* OID form, return FALSE */
			*matchp = 1;
			return LDAP_SUCCESS;
		}

		/* desc form, return undefined */
		return LDAP_INVALID_SYNTAX;
	}

	if ( oc == NULL ) {
		/* unrecognized stored value */
		return LDAP_INVALID_SYNTAX;
	}

	if( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX( flags ) ) {
		*matchp = ( asserted != oc );
	} else {
		*matchp = !is_object_subclass( asserted, oc );
	}

	return LDAP_SUCCESS;
}
Example #3
0
int is_entry_objectclass(
	Entry*	e,
	ObjectClass *oc,
	unsigned flags )
{
	/*
	 * set_flags should only be true if oc is one of operational
	 * object classes which we support objectClass flags for
	 * (e.g., referral, alias, ...).  See <slap.h>.
	 */

	Attribute *attr;
	struct berval *bv;

	assert( !( e == NULL || oc == NULL ) );
	assert( ( flags & SLAP_OCF_MASK ) != SLAP_OCF_MASK );

	if ( e == NULL || oc == NULL ) {
		return 0;
	}

	if ( flags == SLAP_OCF_SET_FLAGS && ( e->e_ocflags & SLAP_OC__END ) )
	{
		/* flags are set, use them */
		return (e->e_ocflags & oc->soc_flags & SLAP_OC__MASK) != 0;
	}

	/*
	 * find objectClass attribute
	 */
	attr = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
	if ( attr == NULL ) {
		/* no objectClass attribute */
		Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") "
			"no objectClass attribute\n",
			e->e_dn == NULL ? "" : e->e_dn,
			oc->soc_oclass.oc_oid );

		/* mark flags as set */
		e->e_ocflags |= SLAP_OC__END;

		return 0;
	}

	for ( bv = attr->a_vals; bv->bv_val; bv++ ) {
		ObjectClass *objectClass = oc_bvfind( bv );

		if ( objectClass == NULL ) {
			/* FIXME: is this acceptable? */
			continue;
		}

		if ( !( flags & SLAP_OCF_SET_FLAGS ) ) {
			if ( objectClass == oc ) {
				return 1;
			}

			if ( ( flags & SLAP_OCF_CHECK_SUP )
				&& is_object_subclass( oc, objectClass ) )
			{
				return 1;
			}
		}

		e->e_ocflags |= objectClass->soc_flags;
	}

	/* mark flags as set */
	e->e_ocflags |= SLAP_OC__END;

	return ( e->e_ocflags & oc->soc_flags & SLAP_OC__MASK ) != 0;
}
Example #4
0
int
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
{
	Operation		*op = bsi->bsi_op;
	backsql_info		*bi = (backsql_info *)op->o_bd->be_private;
	int			i;
	int			rc;

	Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );

	assert( bsi->bsi_e != NULL );

	memset( bsi->bsi_e, 0, sizeof( Entry ) );

	if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
		Entry	*e;

		e = entry_dup( bi->sql_baseObject );
		if ( e == NULL ) {
			return LDAP_NO_MEMORY;
		}
			
		*bsi->bsi_e = *e;
		free( e );
		goto done;
	}

	ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
	ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );

	bsi->bsi_e->e_attrs = NULL;
	bsi->bsi_e->e_private = NULL;

	if ( eid->eid_oc == NULL ) {
		eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
			eid->eid_oc_id );
	}
	bsi->bsi_oc = eid->eid_oc;
	bsi->bsi_c_eid = eid;

#ifndef BACKSQL_ARBITRARY_KEY	
	/* FIXME: unused */
	bsi->bsi_e->e_id = eid->eid_id;
#endif /* ! BACKSQL_ARBITRARY_KEY */
 
	rc = attr_merge_normalize_one( bsi->bsi_e,
			slap_schema.si_ad_objectClass,
			&bsi->bsi_oc->bom_oc->soc_cname,
			bsi->bsi_op->o_tmpmemctx );
	if ( rc != LDAP_SUCCESS ) {
		backsql_entry_clean( op, bsi->bsi_e );
		return rc;
	}

	if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
	{
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"retrieving all attributes\n", 0, 0, 0 );
		avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
				bsi, 0, AVL_INORDER );

	} else {
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"custom attribute list\n", 0, 0, 0 );
		for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
			backsql_at_map_rec	**vat;
			AttributeName		*an = &bsi->bsi_attrs[ i ];
			int			j;

			/* if one of the attributes listed here is
			 * a subtype of another, it must be ignored,
			 * because subtypes are already dealt with
			 * by backsql_supad2at()
			 */
			for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
				/* skip self */
				if ( j == i ) {
					continue;
				}

				/* skip subtypes */
				if ( is_at_subtype( an->an_desc->ad_type,
							bsi->bsi_attrs[ j ].an_desc->ad_type ) )
				{
					goto next;
				}
			}

			rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
			if ( rc != 0 || vat == NULL ) {
				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
						"attribute \"%s\" is not defined "
						"for objectlass \"%s\"\n",
						an->an_name.bv_val, 
						BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
				continue;
			}

			for ( j = 0; vat[j]; j++ ) {
    				backsql_get_attr_vals( vat[j], bsi );
			}

			ch_free( vat );

next:;
		}
	}

	if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
		Attribute	*a_entryUUID,
				**ap;

		a_entryUUID = backsql_operational_entryUUID( bi, eid );
		if ( a_entryUUID != NULL ) {
			for ( ap = &bsi->bsi_e->e_attrs; 
					*ap; 
					ap = &(*ap)->a_next );

			*ap = a_entryUUID;
		}
	}

	if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
			|| an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs )
			|| an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
	{
		ObjectClass	*soc = NULL;

		if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
			Attribute	*a;
			const char	*text = NULL;
			char		textbuf[ 1024 ];
			size_t		textlen = sizeof( textbuf );
			struct berval	bv[ 2 ],
					*nvals;
			int		rc = LDAP_SUCCESS;

			a = attr_find( bsi->bsi_e->e_attrs,
					slap_schema.si_ad_objectClass );
			if ( a != NULL ) {
				nvals = a->a_nvals;

			} else {
				bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
				BER_BVZERO( &bv[ 1 ] );
				nvals = bv;
			}

			rc = structural_class( nvals, &soc, NULL, 
					&text, textbuf, textlen, op->o_tmpmemctx );
			if ( rc != LDAP_SUCCESS ) {
      				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
					"structural_class() failed %d (%s)\n",
					bsi->bsi_e->e_name.bv_val,
					rc, text ? text : "" );
				backsql_entry_clean( op, bsi->bsi_e );
				return rc;
			}

			if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
				if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
					Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
						"computed structuralObjectClass %s "
						"does not match objectClass %s associated "
						"to entry\n",
						bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
						bsi->bsi_oc->bom_oc->soc_cname.bv_val );
					backsql_entry_clean( op, bsi->bsi_e );
					return rc;
				}

      				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
					"computed structuralObjectClass %s "
					"is subclass of objectClass %s associated "
					"to entry\n",
					bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
					bsi->bsi_oc->bom_oc->soc_cname.bv_val );
			}

		} else {
			soc = bsi->bsi_oc->bom_oc;
		}

		rc = attr_merge_normalize_one( bsi->bsi_e,
				slap_schema.si_ad_structuralObjectClass,
				&soc->soc_cname,
				bsi->bsi_op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			backsql_entry_clean( op, bsi->bsi_e );
			return rc;
		}
	}

done:;
	Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );

	return LDAP_SUCCESS;
}
Example #5
0
/*
 * Determine the structural object class from a set of OIDs
 */
int structural_class(
	BerVarray ocs,
	ObjectClass **scp,
	ObjectClass ***socsp,
	const char **text,
	char *textbuf, size_t textlen,
	void *ctx )
{
	int i, nocs;
	ObjectClass *oc, **socs;
	ObjectClass *sc = NULL;
	int scn = -1;

	*text = "structural_class: internal error";

	/* count them */
	for( i=0; ocs[i].bv_val; i++ ) ;
	nocs = i;
	
	socs = slap_sl_malloc( (nocs+1) * sizeof(ObjectClass *), ctx );

	for( i=0; ocs[i].bv_val; i++ ) {
		socs[i] = oc_bvfind( &ocs[i] );

		if( socs[i] == NULL ) {
			snprintf( textbuf, textlen,
				"unrecognized objectClass '%s'",
				ocs[i].bv_val );
			*text = textbuf;
			goto fail;
		}
	}
	socs[i] = NULL;

	for( i=0; ocs[i].bv_val; i++ ) {
		oc = socs[i];
		if( oc->soc_kind == LDAP_SCHEMA_STRUCTURAL ) {
			if( sc == NULL || is_object_subclass( sc, oc ) ) {
				sc = oc;
				scn = i;

			} else if ( !is_object_subclass( oc, sc ) ) {
				int j;
				ObjectClass *xc = NULL;

				/* find common superior */
				for( j=i+1; ocs[j].bv_val; j++ ) {
					xc = socs[j];

					if( xc == NULL ) {
						snprintf( textbuf, textlen,
							"unrecognized objectClass '%s'",
							ocs[j].bv_val );
						*text = textbuf;
						goto fail;
					}

					if( xc->soc_kind != LDAP_SCHEMA_STRUCTURAL ) {
						xc = NULL;
						continue;
					}

					if( is_object_subclass( sc, xc ) &&
						is_object_subclass( oc, xc ) )
					{
						/* found common subclass */
						break;
					}

					xc = NULL;
				}

				if( xc == NULL ) {
					/* no common subclass */
					snprintf( textbuf, textlen,
						"invalid structural object class chain (%s/%s)",
						ocs[scn].bv_val, ocs[i].bv_val );
					*text = textbuf;
					goto fail;
				}
			}
		}
	}

	if( scp ) {
		*scp = sc;
	}

	if( sc == NULL ) {
		*text = "no structural object class provided";
		goto fail;
	}

	if( scn < 0 ) {
		*text = "invalid structural object class";
		goto fail;
	}

	if ( socsp ) {
		*socsp = socs;
	} else {
		slap_sl_free( socs, ctx );
	}
	*text = NULL;

	return LDAP_SUCCESS;

fail:
	slap_sl_free( socs, ctx );
	return LDAP_OBJECT_CLASS_VIOLATION;
}
Example #6
0
int
entry_schema_check( 
	Operation *op,
	Entry *e,
	Attribute *oldattrs,
	int manage,
	int add,
	Attribute **socp,
	const char** text,
	char *textbuf, size_t textlen )
{
	Attribute	*a, *asc = NULL, *aoc = NULL;
	ObjectClass *sc, *oc, **socs = NULL;
	AttributeType *at;
	ContentRule *cr;
	int	rc, i;
	AttributeDescription *ad_structuralObjectClass
		= slap_schema.si_ad_structuralObjectClass;
	AttributeDescription *ad_objectClass
		= slap_schema.si_ad_objectClass;
	int extensible = 0;
	int subentry = is_entry_subentry( e );
	int collectiveSubentry = 0;

	if ( SLAP_NO_SCHEMA_CHECK( op->o_bd )) {
		return LDAP_SUCCESS;
	}

	if ( get_no_schema_check( op ) ) {
		return LDAP_SUCCESS;
	}

	if( subentry ) {
		collectiveSubentry = is_entry_collectiveAttributeSubentry( e );
	}

	*text = textbuf;

	/* misc attribute checks */
	for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
		const char *type = a->a_desc->ad_cname.bv_val;

		/* there should be at least one value */
		assert( a->a_vals != NULL );
		assert( a->a_vals[0].bv_val != NULL ); 

		if( a->a_desc->ad_type->sat_check ) {
			rc = (a->a_desc->ad_type->sat_check)(
				op->o_bd, e, a, text, textbuf, textlen );
			if( rc != LDAP_SUCCESS ) {
				return rc;
			}
		}

		if( a->a_desc == ad_structuralObjectClass )
			asc = a;
		else if ( a->a_desc == ad_objectClass )
			aoc = a;

		if( !collectiveSubentry && is_at_collective( a->a_desc->ad_type ) ) {
			snprintf( textbuf, textlen,
				"'%s' can only appear in collectiveAttributeSubentry",
				type );
			return LDAP_OBJECT_CLASS_VIOLATION;
		}

		/* if single value type, check for multiple values */
		if( is_at_single_value( a->a_desc->ad_type ) &&
			a->a_vals[1].bv_val != NULL )
		{
			Debug(LDAP_DEBUG_ANY,
			      "Entry (%s), attribute '%s' cannot have multiple values\n",
			      e->e_dn, type );

			return LDAP_CONSTRAINT_VIOLATION;
		}
	}

	/* check the object class attribute */
	if ( aoc == NULL ) {
		Debug( LDAP_DEBUG_ANY, "No objectClass for entry (%s)\n",
		    e->e_dn );

		*text = "no objectClass attribute";
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	assert( aoc->a_vals != NULL );
	assert( aoc->a_vals[0].bv_val != NULL );

	/* check the structural object class attribute */
	if ( asc == NULL && !add ) {
		Debug( LDAP_DEBUG_ANY,
			"No structuralObjectClass for entry (%s)\n",
		    e->e_dn );

		*text = "no structuralObjectClass operational attribute";
		return LDAP_OTHER;
	}

	rc = structural_class( aoc->a_vals, &oc, &socs, text, textbuf, textlen,
		op->o_tmpmemctx );
	if( rc != LDAP_SUCCESS ) {
		return rc;
	}

	if ( asc == NULL && add ) {
		attr_merge_one( e, ad_structuralObjectClass, &oc->soc_cname, NULL );
		asc = attr_find( e->e_attrs, ad_structuralObjectClass );
		sc = oc;
		goto got_soc;
	}

	assert( asc->a_vals != NULL );
	assert( asc->a_vals[0].bv_val != NULL );
	assert( asc->a_vals[1].bv_val == NULL );

	sc = oc_bvfind( &asc->a_vals[0] );
	if( sc == NULL ) {
		Debug(LDAP_DEBUG_ANY,
		      "entry_check_schema(%s): unrecognized structuralObjectClass '%s'\n",
		      e->e_dn, asc->a_vals[0].bv_val );

		rc = LDAP_OBJECT_CLASS_VIOLATION;
		goto done;
	}

	if( sc->soc_kind != LDAP_SCHEMA_STRUCTURAL ) {
		Debug(LDAP_DEBUG_ANY,
		      "entry_check_schema(%s): structuralObjectClass '%s' is not STRUCTURAL\n",
		      e->e_dn, asc->a_vals[0].bv_val );

		rc = LDAP_OTHER;
		goto done;
	}

got_soc:
	if( !manage && sc->soc_obsolete ) {
		Debug(LDAP_DEBUG_ANY,
		      "entry_check_schema(%s): structuralObjectClass '%s' is OBSOLETE\n",
		      e->e_dn, asc->a_vals[0].bv_val );

		rc = LDAP_OBJECT_CLASS_VIOLATION;
		goto done;
	}

	*text = textbuf;

	if ( oc == NULL ) {
		snprintf( textbuf, textlen, 
			"unrecognized objectClass '%s'",
			aoc->a_vals[0].bv_val );
		rc = LDAP_OBJECT_CLASS_VIOLATION;
		goto done;

	} 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 */
	if ( !is_entry_glue ( e ) ) {
		rc = entry_naming_check( e, manage, add, text, textbuf, textlen );
		if( rc != LDAP_SUCCESS ) {
			goto done;
		}
	} else {
		/* Glue Entry */
	}

	/* find the content rule for the structural class */
	cr = cr_find( sc->soc_oid );

	/* the cr must be same as the structural class */
	assert( !cr || !strcmp( cr->scr_oid, sc->soc_oid ) );

	/* check that the entry has required attrs of the content rule */
	if( cr ) {
		if( !manage && cr->scr_obsolete ) {
			Debug(LDAP_DEBUG_ANY,
			      "Entry (%s): content rule '%s' is obsolete\n",
			      e->e_dn, ldap_contentrule2name(&cr->scr_crule) );

			rc = LDAP_OBJECT_CLASS_VIOLATION;
			goto done;
		}

		if( cr->scr_required ) for( i=0; cr->scr_required[i]; i++ ) {
			at = cr->scr_required[i];

			for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
				if( a->a_desc->ad_type == at ) {
					break;
				}
			}

			/* not there => schema violation */
			if ( a == NULL ) {
				Debug(LDAP_DEBUG_ANY,
				      "Entry (%s): content rule '%s' requires attribute '%s'\n",
				      e->e_dn,
				      ldap_contentrule2name(&cr->scr_crule),
				      at->sat_cname.bv_val );

				rc = LDAP_OBJECT_CLASS_VIOLATION;
				goto done;
			}
		}

		if( cr->scr_precluded ) for( i=0; cr->scr_precluded[i]; i++ ) {
			at = cr->scr_precluded[i];

			for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
				if( a->a_desc->ad_type == at ) {
					break;
				}
			}

			/* there => schema violation */
			if ( a != NULL ) {
				Debug(LDAP_DEBUG_ANY,
				      "Entry (%s): content rule '%s' precluded attribute '%s'\n",
				      e->e_dn,
				      ldap_contentrule2name(&cr->scr_crule),
				      at->sat_cname.bv_val );

				rc = LDAP_OBJECT_CLASS_VIOLATION;
				goto done;
			}
		}
	}

	/* check that the entry has required attrs for each oc */
	for ( i = 0; socs[i]; i++ ) {
		oc = socs[i];
		if ( !manage && oc->soc_obsolete ) {
			/* disallow obsolete classes */
			Debug(LDAP_DEBUG_ANY,
			      "entry_check_schema(%s): objectClass '%s' is OBSOLETE\n",
			      e->e_dn, aoc->a_vals[i].bv_val );

			rc = LDAP_OBJECT_CLASS_VIOLATION;
			goto done;
		}

		if ( oc->soc_check ) {
			rc = (oc->soc_check)( op->o_bd, e, oc,
				text, textbuf, textlen );
			if( rc != LDAP_SUCCESS ) {
				goto done;
			}
		}

		if ( oc->soc_kind == LDAP_SCHEMA_ABSTRACT ) {
			/* object class is abstract */
			if ( oc != slap_schema.si_oc_top &&
				!is_object_subclass( oc, sc ))
			{
				int j;
				ObjectClass *xc = NULL;
				for( j=0; socs[j]; j++ ) {
					if( i != j ) {
						xc = socs[j];

						/* since we previous check against the
						 * structural object of this entry, the
						 * abstract class must be a (direct or indirect)
						 * superclass of one of the auxiliary classes of
						 * the entry.
						 */
						if ( xc->soc_kind == LDAP_SCHEMA_AUXILIARY &&
							is_object_subclass( oc, xc ) )
						{
							xc = NULL;
							break;
						}
					}
				}

				if( xc != NULL ) {
					Debug(LDAP_DEBUG_ANY,
					      "entry_check_schema(%s): instantiation of " "abstract objectClass '%s' not allowed\n",
					      e->e_dn, aoc->a_vals[i].bv_val );

					rc = LDAP_OBJECT_CLASS_VIOLATION;
					goto done;
				}
			}

		} else if ( oc->soc_kind != LDAP_SCHEMA_STRUCTURAL || oc == sc ) {
			char *s;

			if( oc->soc_kind == LDAP_SCHEMA_AUXILIARY ) {
				int k;

				if( cr ) {
					int j;

					k = -1;
					if( cr->scr_auxiliaries ) {
						for( j = 0; cr->scr_auxiliaries[j]; j++ ) {
							if( cr->scr_auxiliaries[j] == oc ) {
								k = 0;
								break;
							}
						}
					}
					if ( k ) {
						snprintf( textbuf, textlen, 
							"class '%s' not allowed by content rule '%s'",
							oc->soc_cname.bv_val,
							ldap_contentrule2name( &cr->scr_crule ) );
					}
				} else if ( global_disallows & SLAP_DISALLOW_AUX_WO_CR ) {
					k = -1;
					snprintf( textbuf, textlen, 
						"class '%s' not allowed by any content rule",
						oc->soc_cname.bv_val );
				} else {
					k = 0;	
				}

				if( k == -1 ) {
					Debug( LDAP_DEBUG_ANY,
						"Entry (%s): %s\n",
						e->e_dn, textbuf );

					rc = LDAP_OBJECT_CLASS_VIOLATION;
					goto done;
				}
			}

			s = oc_check_required( e, oc, &aoc->a_vals[i] );
			if (s != NULL) {
				Debug(LDAP_DEBUG_ANY,
				      "Entry (%s): object class '%s' requires attribute '%s'\n",
				      e->e_dn, aoc->a_vals[i].bv_val, s );

				rc = LDAP_OBJECT_CLASS_VIOLATION;
				goto done;
			}

			if( oc == slap_schema.si_oc_extensibleObject ) {
				extensible=1;
			}
		}
	}

	if( extensible ) {
		*text = NULL;
		rc = LDAP_SUCCESS;
		goto done;
	}

	/* check that each attr in the entry is allowed by some oc */
	for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
 		rc = LDAP_OBJECT_CLASS_VIOLATION;

		if( cr && cr->scr_required ) {
			for( i=0; cr->scr_required[i]; i++ ) {
				if( cr->scr_required[i] == a->a_desc->ad_type ) {
					rc = LDAP_SUCCESS;
					break;
				}
			}
		}

		if( rc != LDAP_SUCCESS && cr && cr->scr_allowed ) {
			for( i=0; cr->scr_allowed[i]; i++ ) {
				if( cr->scr_allowed[i] == a->a_desc->ad_type ) {
					rc = LDAP_SUCCESS;
					break;
				}
			}
		}

		if( rc != LDAP_SUCCESS ) 
		{
			rc = oc_check_allowed( a->a_desc->ad_type, socs, sc );
		}

		if ( rc != LDAP_SUCCESS ) {
			char *type = a->a_desc->ad_cname.bv_val;

			Debug(LDAP_DEBUG_ANY,
			      "Entry (%s), attribute '%s' not allowed\n",
			      e->e_dn, type );

			goto done;
		}
	}

	*text = NULL;
done:
	slap_sl_free( socs, op->o_tmpmemctx );
	return rc;
}