From 49d16c4dceb9011da3ac7e2f11545c1a2320cc6b Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 19 Dec 2001 22:08:24 +0000 Subject: [PATCH] Add structuralObjectClass support and a bit of const'ification --- servers/slapd/add.c | 2 +- servers/slapd/modify.c | 28 ++++- servers/slapd/mr.c | 2 +- servers/slapd/proto-slap.h | 11 +- servers/slapd/schema_check.c | 220 +++++++++++++++++++++++++++++++---- servers/slapd/syntax.c | 4 +- 6 files changed, 232 insertions(+), 35 deletions(-) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 046ae39378..679411fbcd 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -266,7 +266,7 @@ do_add( Connection *conn, Operation *op ) assert( (*modstail)->sml_op == LDAP_MOD_ADD ); assert( (*modstail)->sml_desc != NULL ); } - rc = slap_mods_opattrs( op, modstail, &text ); + rc = slap_mods_opattrs( op, mods, modstail, &text ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 6c882c7ab5..e23dfa8ce6 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -348,7 +348,7 @@ do_modify( { /* empty */ } - rc = slap_mods_opattrs( op, modstail, &text ); + rc = slap_mods_opattrs( op, mods, modstail, &text ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, @@ -563,6 +563,7 @@ int slap_modlist2mods( int slap_mods_opattrs( Operation *op, + Modifications *mods, Modifications **modtail, const char **text ) { @@ -599,17 +600,34 @@ int slap_mods_opattrs( } if( op->o_tag == LDAP_REQ_ADD ) { - struct berval uuid; + struct berval tmpval; char uuidbuf[40]; + int rc; - uuid.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) ); - uuid.bv_val = uuidbuf; + rc = mods_structural_class( mods, &tmpval, text ); + if( rc != LDAP_SUCCESS ) { + return rc; + } + if ( tmpval.bv_len ) { + mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ) ); + mod->sml_op = mop; + mod->sml_desc = slap_schema.si_ad_structuralObjectClass; + mod->sml_bvalues = (struct berval **) malloc( 2 * sizeof( struct berval * ) ); + mod->sml_bvalues[0] = ber_bvdup( &tmpval ); + mod->sml_bvalues[1] = NULL; + assert( mod->sml_bvalues[0] ); + *modtail = mod; + modtail = &mod->sml_next; + } + + tmpval.bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) ); + tmpval.bv_val = uuidbuf; mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ) ); mod->sml_op = mop; mod->sml_desc = slap_schema.si_ad_entryUUID; mod->sml_bvalues = (struct berval **) malloc( 2 * sizeof( struct berval * ) ); - mod->sml_bvalues[0] = ber_bvdup( &uuid ); + mod->sml_bvalues[0] = ber_bvdup( &tmpval ); mod->sml_bvalues[1] = NULL; assert( mod->sml_bvalues[0] ); *modtail = mod; diff --git a/servers/slapd/mr.c b/servers/slapd/mr.c index 2ec9ebcc15..52bdbe96eb 100644 --- a/servers/slapd/mr.c +++ b/servers/slapd/mr.c @@ -165,7 +165,7 @@ mr_add( int register_matching_rule( - char * desc, + const char * desc, unsigned usage, slap_mr_convert_func *convert, slap_mr_normalize_func *normalize, diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 9912982010..708928d760 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -450,6 +450,7 @@ LDAP_SLAPD_F( int ) slap_modlist2mods( LDAP_SLAPD_F( int ) slap_mods_opattrs( Operation *op, + Modifications *mods, Modifications **modlist, const char **text ); @@ -693,14 +694,14 @@ LDAP_SLAPD_F (int) mr_add LDAP_P((LDAPMatchingRule *mr, const char **err)); LDAP_SLAPD_F (int) register_syntax LDAP_P(( - char *desc, + const char *desc, unsigned flags, slap_syntax_validate_func *validate, slap_syntax_transform_func *normalize, slap_syntax_transform_func *pretty )); LDAP_SLAPD_F (int) register_matching_rule LDAP_P(( - char * desc, + const char * desc, unsigned usage, slap_mr_convert_func *convert, slap_mr_normalize_func *normalize, @@ -727,6 +728,10 @@ LDAP_SLAPD_F (int) entry_schema_check LDAP_P(( Entry *e, Attribute *attrs, const char** text, char *textbuf, size_t textlen )); +LDAP_SLAPD_F (int) mods_structural_class LDAP_P(( + Modifications *mods, + struct berval *oc, + const char** text )); /* @@ -941,8 +946,6 @@ LDAP_SLAPD_F (int) slap_startup LDAP_P(( Backend *be )); LDAP_SLAPD_F (int) slap_shutdown LDAP_P(( Backend *be )); LDAP_SLAPD_F (int) slap_destroy LDAP_P((void)); -struct sockaddr_in; - LDAP_SLAPD_F (void) slapd_add_internal(ber_socket_t s); LDAP_SLAPD_F (int) slapd_daemon_init( const char *urls ); LDAP_SLAPD_F (int) slapd_daemon_destroy(void); diff --git a/servers/slapd/schema_check.c b/servers/slapd/schema_check.c index 87ba819c1d..d8ae713294 100644 --- a/servers/slapd/schema_check.c +++ b/servers/slapd/schema_check.c @@ -16,7 +16,89 @@ #include "slap.h" #include "ldap_pvt.h" -static char * oc_check_required(Entry *e, struct berval *ocname); +static char * oc_check_required( + Entry *e, + ObjectClass *oc, + struct berval *ocname ); + +/* + * Determine the structural object class from a set of OIDs + */ +static int structural_class( + struct berval **ocs, + struct berval *scbv, + const char **text ) +{ + int i; + ObjectClass *oc; + ObjectClass *sc = NULL; + int scn = 0; + + *text = "structural object error"; + scbv->bv_len = 0; + + for( i=0; ocs[i]; i++ ) { + oc = oc_find( ocs[i]->bv_val ); + + if( oc == NULL ) { + *text = "unrecongized objectClass attribute"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + + 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 ) ) { + /* FIXME: multiple inheritance possible! */ + *text = "invalid strucutural object class chain"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + } + } + + if( sc == NULL ) { + *text = "no strucutural object classes"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + + *scbv = *ocs[scn]; + return LDAP_SUCCESS; +} + +/* + * Return structural object class from list of modifications + */ +int mods_structural_class( + Modifications *mods, + struct berval *sc, + const char **text ) +{ + Modifications *ocmod = NULL; + + for( ; mods != NULL; mods = mods->sml_next ) { + if( mods->sml_desc == slap_schema.si_ad_objectClass ) { + if( ocmod != NULL ) { + *text = "entry has multiple objectClass attributes"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + ocmod = mods; + } + } + + if( ocmod == NULL ) { + *text = "entry has no objectClass attribute"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + + if( ocmod->sml_bvalues == NULL || ocmod->sml_bvalues[0] == NULL ) { + *text = "objectClass attribute has no values"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + + return structural_class( ocmod->sml_bvalues, sc, text ); +} /* * entry_schema_check - check that entry e conforms to the schema required @@ -27,13 +109,18 @@ static char * oc_check_required(Entry *e, struct berval *ocname); int entry_schema_check( - Entry *e, Attribute *oldattrs, const char** text, + Entry *e, Attribute *oldattrs, + const char** text, char *textbuf, size_t textlen ) { - Attribute *a, *aoc; - ObjectClass *oc; - int i; - AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; + Attribute *a, *asc, *aoc; + ObjectClass *sc, *oc; + int rc, i; + struct berval nsc; + AttributeDescription *ad_structuralObjectClass + = slap_schema.si_ad_structuralObjectClass; + AttributeDescription *ad_objectClass + = slap_schema.si_ad_objectClass; int extensible = 0; *text = textbuf; @@ -70,11 +157,72 @@ entry_schema_check( if( !global_schemacheck ) return LDAP_SUCCESS; +#if 1 /* find the object class attribute - could error out here */ - if ( (aoc = attr_find( e->e_attrs, ad_objectClass )) == NULL ) { + asc = attr_find( e->e_attrs, ad_structuralObjectClass ); + if ( asc == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "schema", LDAP_LEVEL_INFO, "entry_schema_check: " + "No structuralObjectClass for entry (%s)\n", + e->e_dn )); +#else + Debug( LDAP_DEBUG_ANY, + "No structuralObjectClass for entry (%s)\n", + e->e_dn, 0, 0 ); +#endif + + *text = "no structuralObjectClass operational attribute"; + return LDAP_OBJECT_CLASS_VIOLATION; + } + + assert( asc->a_vals != NULL ); + assert( asc->a_vals[0] != NULL ); + assert( asc->a_vals[1] == NULL ); + + sc = oc_find( asc->a_vals[0]->bv_val ); + if( sc == NULL ) { + snprintf( textbuf, textlen, + "unrecognized structuralObjectClass '%s'", + aoc->a_vals[0]->bv_val ); + +#ifdef NEW_LOGGING + LDAP_LOG(( "schema", LDAP_LEVEL_INFO, + "entry_schema_check: dn (%s), %s\n", + e->e_dn, textbuf )); +#else + Debug( LDAP_DEBUG_ANY, + "entry_check_schema(%s): %s\n", + e->e_dn, textbuf, 0 ); +#endif + + return LDAP_OBJECT_CLASS_VIOLATION; + } + + if( sc->soc_kind != LDAP_SCHEMA_STRUCTURAL ) { + snprintf( textbuf, textlen, + "structuralObjectClass '%s' is not STRUCTURAL", + aoc->a_vals[0]->bv_val ); + +#ifdef NEW_LOGGING + LDAP_LOG(( "schema", LDAP_LEVEL_INFO, + "entry_schema_check: dn (%s), %s\n", + e->e_dn, textbuf )); +#else + Debug( LDAP_DEBUG_ANY, + "entry_check_schema(%s): %s\n", + e->e_dn, textbuf, 0 ); +#endif + + return LDAP_OBJECT_CLASS_VIOLATION; + } +#endif + + /* find the object class attribute */ + aoc = attr_find( e->e_attrs, ad_objectClass ); + if ( aoc == NULL ) { #ifdef NEW_LOGGING LDAP_LOG(( "schema", LDAP_LEVEL_INFO, - "entry_schema_check: No objectClass for entry (%s).\n", e->e_dn )); + "entry_schema_check: No objectClass for entry (%s).\n", e->e_dn )); #else Debug( LDAP_DEBUG_ANY, "No objectClass for entry (%s)\n", e->e_dn, 0, 0 ); @@ -84,6 +232,30 @@ entry_schema_check( return LDAP_OBJECT_CLASS_VIOLATION; } + assert( aoc->a_vals != NULL ); + assert( aoc->a_vals[0] != NULL ); + + rc = structural_class( aoc->a_vals, &nsc, text ); + if( rc != LDAP_SUCCESS ) { + return rc; + } else if ( nsc.bv_len == 0 ) { + return LDAP_OBJECT_CLASS_VIOLATION; + } + + oc = oc_find( nsc.bv_val ); + if ( oc == NULL ) { + snprintf( textbuf, textlen, + "unrecognized objectClass '%s'", + aoc->a_vals[i]->bv_val ); + return LDAP_OBJECT_CLASS_VIOLATION; + + } else if ( sc != oc ) { + snprintf( textbuf, textlen, + "structuralObjectClass modification from '%s' to '%s' not allowed", + asc->a_vals[0]->bv_val, nsc.bv_val ); + return LDAP_NO_OBJECT_CLASS_MODS; + } + /* check that the entry has required attrs for each oc */ for ( i = 0; aoc->a_vals[i] != NULL; i++ ) { if ( (oc = oc_find( aoc->a_vals[i]->bv_val )) == NULL ) { @@ -103,8 +275,16 @@ entry_schema_check( return LDAP_OBJECT_CLASS_VIOLATION; + } else if ( oc->soc_kind == LDAP_SCHEMA_ABSTRACT ) { + /* object class is abstract */ + /* FIXME: need to check that is is a superclass of something */ + + } else if ( oc->soc_kind == LDAP_SCHEMA_STRUCTURAL && oc != sc ) { + /* object class is a superclass of the structural class */ + /* nothing in particular to check */ + } else { - char *s = oc_check_required( e, aoc->a_vals[i] ); + char *s = oc_check_required( e, oc, aoc->a_vals[i] ); if (s != NULL) { snprintf( textbuf, textlen, @@ -127,7 +307,6 @@ entry_schema_check( if( oc == slap_schema.si_oc_extensibleObject ) { extensible=1; } - } } @@ -163,29 +342,26 @@ entry_schema_check( } static char * -oc_check_required( Entry *e, struct berval *ocname ) +oc_check_required( + Entry *e, + ObjectClass *oc, + struct berval *ocname ) { - ObjectClass *oc; AttributeType *at; int i; Attribute *a; #ifdef NEW_LOGGING LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY, - "oc_check_required: dn (%s), objectClass \"%s\"\n", - e->e_dn, ocname->bv_val )); + "oc_check_required: dn (%s), objectClass \"%s\"\n", + e->e_dn, ocname->bv_val )); #else Debug( LDAP_DEBUG_TRACE, - "oc_check_required entry (%s), objectClass \"%s\"\n", - e->e_dn, ocname->bv_val, 0 ); + "oc_check_required entry (%s), objectClass \"%s\"\n", + e->e_dn, ocname->bv_val, 0 ); #endif - /* find global oc defn. it we don't know about it assume it's ok */ - if ( (oc = oc_find( ocname->bv_val )) == NULL ) { - return NULL; - } - /* check for empty oc_required */ if(oc->soc_required == NULL) { return NULL; @@ -218,7 +394,7 @@ int oc_check_allowed( #ifdef NEW_LOGGING LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY, - "oc_check_allowed: type \"%s\"\n", at->sat_cname.bv_val )); + "oc_check_allowed: type \"%s\"\n", at->sat_cname.bv_val )); #else Debug( LDAP_DEBUG_TRACE, "oc_check_allowed type \"%s\"\n", diff --git a/servers/slapd/syntax.c b/servers/slapd/syntax.c index 25ca0258ff..78bddd3276 100644 --- a/servers/slapd/syntax.c +++ b/servers/slapd/syntax.c @@ -36,7 +36,7 @@ syn_index_cmp( static int syn_index_name_cmp( - char *name, + const char *name, struct sindexrec *sir ) { @@ -150,7 +150,7 @@ syn_add( int register_syntax( - char * desc, + const char * desc, unsigned flags, slap_syntax_validate_func *validate, slap_syntax_transform_func *normalize, -- 2.39.5