Implement content rule checks

w/ implicit default rules allowing any auxiliary class to be mixed in
This commit is contained in:
Kurt Zeilenga 2002-10-09 23:02:01 +00:00
parent e6d10b9590
commit 1aa829922f
2 changed files with 150 additions and 3 deletions

View File

@ -38,6 +38,10 @@ entry_schema_check(
{ {
Attribute *a, *asc, *aoc; Attribute *a, *asc, *aoc;
ObjectClass *sc, *oc; ObjectClass *sc, *oc;
#ifdef SLAP_EXTENDED_SCHEMA
AttributeType *at;
ContentRule *cr;
#endif
int rc, i; int rc, i;
struct berval nsc; struct berval nsc;
AttributeDescription *ad_structuralObjectClass AttributeDescription *ad_structuralObjectClass
@ -48,7 +52,9 @@ entry_schema_check(
int subentry = is_entry_subentry( e ); int subentry = is_entry_subentry( e );
int collectiveSubentry = 0; int collectiveSubentry = 0;
if( subentry) collectiveSubentry = is_entry_collectiveAttributeSubentry( e ); if( subentry ) {
collectiveSubentry = is_entry_collectiveAttributeSubentry( e );
}
*text = textbuf; *text = textbuf;
@ -194,6 +200,77 @@ entry_schema_check(
return LDAP_NO_OBJECT_CLASS_MODS; return LDAP_NO_OBJECT_CLASS_MODS;
} }
#ifdef SLAP_EXTENDED_SCHEMA
/* 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 && 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 ) {
snprintf( textbuf, textlen,
"content rule '%s' requires attribute '%s'",
ldap_contentrule2name( &cr->scr_crule ),
at->sat_cname.bv_val );
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, INFO,
"entry_schema_check: dn=\"%s\" %s", e->e_dn, textbuf, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"Entry (%s): %s\n",
e->e_dn, textbuf, 0 );
#endif
return LDAP_OBJECT_CLASS_VIOLATION;
}
}
}
if( cr && 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 ) {
snprintf( textbuf, textlen,
"content rule '%s' precluded attribute '%s'",
ldap_contentrule2name( &cr->scr_crule ),
at->sat_cname.bv_val );
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, INFO,
"entry_schema_check: dn=\"%s\" %s", e->e_dn, textbuf, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"Entry (%s): %s\n",
e->e_dn, textbuf, 0 );
#endif
return LDAP_OBJECT_CLASS_VIOLATION;
}
}
}
#endif /* SLAP_EXTENDED_SCHEMA */
/* check that the entry has required attrs for each oc */ /* check that the entry has required attrs for each oc */
for ( i = 0; aoc->a_vals[i].bv_val != NULL; i++ ) { for ( i = 0; aoc->a_vals[i].bv_val != NULL; i++ ) {
if ( (oc = oc_bvfind( &aoc->a_vals[i] )) == NULL ) { if ( (oc = oc_bvfind( &aoc->a_vals[i] )) == NULL ) {
@ -284,8 +361,46 @@ entry_schema_check(
} }
} else if ( oc->soc_kind != LDAP_SCHEMA_STRUCTURAL || oc == sc ) { } else if ( oc->soc_kind != LDAP_SCHEMA_STRUCTURAL || oc == sc ) {
char *s = oc_check_required( e, oc, &aoc->a_vals[i] ); char *s;
#ifdef SLAP_EXTENDED_SCHEMA
if( oc->soc_kind == LDAP_SCHEMA_AUXILIARY ) {
int k=0;
if( cr ) {
if( cr->scr_auxiliaries ) {
for( ; cr->scr_auxiliaries[k]; k++ ) {
if( cr->scr_auxiliaries[k] == oc ) {
k=-1;
break;
}
}
}
} else if ( global_disallows & SLAP_DISALLOW_AUX_WO_CR ) {
k=-1;
}
if( k == -1 ) {
snprintf( textbuf, textlen,
"content rule '%s' does not allow class '%s'",
ldap_contentrule2name( &cr->scr_crule ),
oc->soc_cname.bv_val );
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, INFO,
"entry_schema_check: dn=\"%s\" %s",
e->e_dn, textbuf, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"Entry (%s): %s\n",
e->e_dn, textbuf, 0 );
#endif
return LDAP_OBJECT_CLASS_VIOLATION;
}
}
#endif /* SLAP_EXTENDED_SCHEMA */
s = oc_check_required( e, oc, &aoc->a_vals[i] );
if (s != NULL) { if (s != NULL) {
snprintf( textbuf, textlen, snprintf( textbuf, textlen,
"object class '%s' requires attribute '%s'", "object class '%s' requires attribute '%s'",
@ -315,7 +430,35 @@ entry_schema_check(
/* check that each attr in the entry is allowed by some oc */ /* check that each attr in the entry is allowed by some oc */
for ( a = e->e_attrs; a != NULL; a = a->a_next ) { for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
int ret = oc_check_allowed( a->a_desc->ad_type, aoc->a_vals, sc ); int ret;
#ifdef SLAP_EXTENDED_SCHEMA
ret = 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 ) {
ret = LDAP_SUCCESS;
break;
}
}
}
if( ret != LDAP_SUCCESS && cr && cr->scr_allowed ) {
for( i=0; cr->scr_allowed[i]; i++ ) {
if( cr->scr_allowed[i] == a->a_desc->ad_type ) {
ret = LDAP_SUCCESS;
break;
}
}
}
if( ret != LDAP_SUCCESS )
#endif /* SLAP_EXTENDED_SCHEMA */
{
ret = oc_check_allowed( a->a_desc->ad_type, aoc->a_vals, sc );
}
if ( ret != LDAP_SUCCESS ) { if ( ret != LDAP_SUCCESS ) {
char *type = a->a_desc->ad_cname.bv_val; char *type = a->a_desc->ad_cname.bv_val;

View File

@ -35,6 +35,8 @@
#include "ldap_pvt_thread.h" #include "ldap_pvt_thread.h"
#include "ldap_queue.h" #include "ldap_queue.h"
#define SLAP_EXTENDED_SCHEMA 1
LDAP_BEGIN_DECL LDAP_BEGIN_DECL
/* /*
* SLAPD Memory allocation macros * SLAPD Memory allocation macros
@ -1270,6 +1272,8 @@ struct slap_backend_db {
#define SLAP_DISALLOW_TLS_2_ANON 0x0010U /* StartTLS -> Anonymous */ #define SLAP_DISALLOW_TLS_2_ANON 0x0010U /* StartTLS -> Anonymous */
#define SLAP_DISALLOW_TLS_AUTHC 0x0020U /* TLS while authenticated */ #define SLAP_DISALLOW_TLS_AUTHC 0x0020U /* TLS while authenticated */
#define SLAP_DISALLOW_AUX_WO_CR 0x4000U
slap_mask_t be_requires; /* pre-operation requirements */ slap_mask_t be_requires; /* pre-operation requirements */
#define SLAP_REQUIRE_BIND 0x0001U /* bind before op */ #define SLAP_REQUIRE_BIND 0x0001U /* bind before op */
#define SLAP_REQUIRE_LDAP_V3 0x0002U /* LDAPv3 before op */ #define SLAP_REQUIRE_LDAP_V3 0x0002U /* LDAPv3 before op */