]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/schema_check.c
Fix cursor initialization, scope IDs
[openldap] / servers / slapd / schema_check.c
index ac1986161be24c37062bf8e0da17fdc7770a7446..0cc09ddb0415aeaaee247e3bcd75e1a4600f79a6 100644 (file)
@@ -1,7 +1,7 @@
 /* schema_check.c - routines to enforce schema definitions */
 /* $OpenLDAP$ */
 /*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
@@ -21,6 +21,10 @@ static char * oc_check_required(
        ObjectClass *oc,
        struct berval *ocname );
 
+static int entry_naming_check(
+       Entry *e,
+       const char** text,
+       char *textbuf, size_t textlen );
 /*
  * entry_schema_check - check that entry e conforms to the schema required
  * by its object class(es).
@@ -161,6 +165,23 @@ entry_schema_check(
                return LDAP_OTHER;
        }
 
+       if( sc->soc_obsolete ) {
+               snprintf( textbuf, textlen, 
+                       "structuralObjectClass '%s' is OBSOLETE",
+                       asc->a_vals[0].bv_val );
+
+#ifdef NEW_LOGGING
+               LDAP_LOG( OPERATION, INFO, 
+                       "entry_schema_check: dn (%s), %s\n", e->e_dn, textbuf, 0 );
+#else
+               Debug( LDAP_DEBUG_ANY,
+                       "entry_check_schema(%s): %s\n",
+                       e->e_dn, textbuf, 0 );
+#endif
+
+               return LDAP_OBJECT_CLASS_VIOLATION;
+       }
+
        /* find the object class attribute */
        aoc = attr_find( e->e_attrs, ad_objectClass );
        if ( aoc == NULL ) {
@@ -195,11 +216,18 @@ entry_schema_check(
 
        } else if ( sc != oc ) {
                snprintf( textbuf, textlen, 
-                       "structural object class modification from '%s' to '%s' not allowed",
+                       "structural object class modification "
+                       "from '%s' to '%s' not allowed",
                        asc->a_vals[0].bv_val, nsc.bv_val );
                return LDAP_NO_OBJECT_CLASS_MODS;
        }
 
+       /* naming check */
+       rc = entry_naming_check( e, text, textbuf, textlen );
+       if( rc != LDAP_SUCCESS ) {
+               return rc;
+       }
+
 #ifdef SLAP_EXTENDED_SCHEMA
        /* find the content rule for the structural class */
        cr = cr_find( sc->soc_oid );
@@ -208,8 +236,25 @@ entry_schema_check(
        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++ ) {
+       if( cr ) {
+               if( cr->scr_obsolete ) {
+                       snprintf( textbuf, textlen, 
+                               "content rule '%s' is obsolete",
+                               ldap_contentrule2name( &cr->scr_crule ));
+
+#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->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 ) {
@@ -237,10 +282,8 @@ entry_schema_check(
                                return LDAP_OBJECT_CLASS_VIOLATION;
                        }
                }
-       }
 
-       if( cr && cr->scr_precluded ) {
-               for( i=0; cr->scr_precluded[i]; i++ ) {
+               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 ) {
@@ -278,6 +321,24 @@ entry_schema_check(
                                "unrecognized objectClass '%s'",
                                aoc->a_vals[i].bv_val );
 
+#ifdef NEW_LOGGING
+                       LDAP_LOG( OPERATION, INFO, 
+                               "entry_schema_check: dn (%s), %s\n", e->e_dn, textbuf, 0 );
+#else
+                       Debug( LDAP_DEBUG_ANY,
+                               "entry_check_schema(%s): %s\n",
+                               e->e_dn, textbuf, 0 );
+#endif
+
+                       return LDAP_OBJECT_CLASS_VIOLATION;
+               }
+
+               if ( oc->soc_obsolete ) {
+                       /* disallow obsolete classes */
+                       snprintf( textbuf, textlen, 
+                               "objectClass '%s' is OBSOLETE",
+                               aoc->a_vals[i].bv_val );
+
 #ifdef NEW_LOGGING
                        LDAP_LOG( OPERATION, INFO, 
                                "entry_schema_check: dn (%s), %s\n", e->e_dn, textbuf, 0 );
@@ -687,7 +748,7 @@ int structural_class(
        }
 
        if( sc == NULL ) {
-               *text = "no structural object classes provided";
+               *text = "no structural object class provided";
                return LDAP_OBJECT_CLASS_VIOLATION;
        }
 
@@ -740,3 +801,75 @@ int mods_structural_class(
        return structural_class( ocmod->sml_bvalues, sc, NULL,
                text, textbuf, textlen );
 }
+
+
+static int
+entry_naming_check(
+       Entry *e,
+       const char** text,
+       char *textbuf, size_t textlen )
+{
+       /* naming check */
+       LDAPRDN         *rdn = NULL;
+       const char      *p = NULL;
+       ber_len_t       cnt;
+       int             rc = LDAP_SUCCESS;
+
+       /*
+        * Get attribute type(s) and attribute value(s) of our RDN
+        */
+       if ( ldap_bv2rdn( &e->e_name, &rdn, (char **)&p,
+               LDAP_DN_FORMAT_LDAP ) )
+       {
+               *text = "unrecongized attribute type(s) in RDN";
+               return LDAP_INVALID_DN_SYNTAX;
+       }
+
+       /* Check that each AVA of the RDN is present in the entry */
+       /* FIXME: Should also check that each AVA lists a distinct type */
+       for ( cnt = 0; rdn[0][cnt]; cnt++ ) {
+               LDAPAVA *ava = rdn[0][cnt];
+               AttributeDescription *desc = NULL;
+               Attribute *attr;
+               const char *errtext;
+
+               rc = slap_bv2ad( &ava->la_attr, &desc, &errtext );
+               if ( rc != LDAP_SUCCESS ) {
+                       snprintf( textbuf, textlen, "%s (in RDN)", errtext );
+                       break;
+               }
+
+               /* find the naming attribute */
+               attr = attr_find( e->e_attrs, desc );
+               if ( attr == NULL ) {
+                       snprintf( textbuf, textlen, 
+                               "naming attribute '%s' is not present in entry",
+                               ava->la_attr.bv_val );
+                       rc = LDAP_NAMING_VIOLATION;
+                       break;
+               }
+
+               if( ava->la_flags & LDAP_AVA_BINARY ) {
+                       snprintf( textbuf, textlen, 
+                               "value of naming attribute '%s' in unsupported BER form",
+                               ava->la_attr.bv_val );
+                       rc = LDAP_NAMING_VIOLATION;
+               }
+
+               if ( value_find_ex( desc,
+                       SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
+                       attr->a_nvals,
+                       &ava->la_value ) != 0 )
+               {
+                       snprintf( textbuf, textlen, 
+                               "value of naming attribute '%s' is not present in entry",
+                               ava->la_attr.bv_val );
+                       rc = LDAP_NAMING_VIOLATION;
+                       break;
+               }
+       }
+
+       ldap_rdnfree( rdn );
+       return rc;
+}
+