]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/schema.c
Revert ITS#3353 patch, it needs to be reworked.
[openldap] / servers / slapd / schema.c
index 05dbd557776223c31098cd61c1172c32576a0653..69d243b04d5dc4fb540fc7483b212111b121f6eb 100644 (file)
-/* schema.c - routines to enforce schema definitions */
+/* schema.c - routines to manage schema definitions */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2004 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
 
 #include "portable.h"
 
 #include <stdio.h>
 
+#include <ac/ctype.h>
 #include <ac/string.h>
 #include <ac/socket.h>
 
 #include "slap.h"
+#include "lutil.h"
 
-static struct objclass *oc_find(char *ocname);
-static int             oc_check_required(Entry *e, char *ocname);
-static int             oc_check_allowed(char *type, struct berval **ocl);
-
-/*
- * oc_check - check that entry e conforms to the schema required by
- * its object class(es). returns 0 if so, non-zero otherwise.
- */
 
 int
-oc_schema_check( Entry *e )
+schema_info( Entry **entry, const char **text )
 {
-       Attribute       *a, *aoc;
-       struct objclass *oc;
-       int             i;
-       int             ret = 0;
-
-       /* find the object class attribute - could error out here */
-       if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) {
-               Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n",
-                   e->e_dn, 0, 0 );
-               return( 0 );
+       AttributeDescription *ad_structuralObjectClass
+               = slap_schema.si_ad_structuralObjectClass;
+       AttributeDescription *ad_objectClass
+               = slap_schema.si_ad_objectClass;
+       AttributeDescription *ad_createTimestamp
+               = slap_schema.si_ad_createTimestamp;
+       AttributeDescription *ad_modifyTimestamp
+               = slap_schema.si_ad_modifyTimestamp;
+
+       Entry           *e;
+       struct berval   vals[5];
+       struct berval   nvals[5];
+
+       e = (Entry *) SLAP_CALLOC( 1, sizeof(Entry) );
+       if( e == NULL ) {
+               /* Out of memory, do something about it */
+               Debug( LDAP_DEBUG_ANY, 
+                       "schema_info: SLAP_CALLOC failed - out of memory.\n", 0, 0, 0 );
+               *text = "out of memory";
+               return LDAP_OTHER;
        }
 
-       /* check that the entry has required attrs for each oc */
-       for ( i = 0; aoc->a_vals[i] != NULL; i++ ) {
-               if ( oc_check_required( e, aoc->a_vals[i]->bv_val ) != 0 ) {
-                       Debug( LDAP_DEBUG_ANY,
-                           "Entry (%s), required attr (%s) missing\n",
-                           e->e_dn, aoc->a_vals[i]->bv_val, 0 );
-                       ret = 1;
-               }
+       e->e_attrs = NULL;
+       /* backend-specific schema info should be created by the
+        * backend itself
+        */
+       ber_dupbv( &e->e_name, &frontendDB->be_schemadn );
+       ber_dupbv( &e->e_nname, &frontendDB->be_schemandn );
+       e->e_private = NULL;
+
+       BER_BVSTR( &vals[0], "subentry" );
+       if( attr_merge_one( e, ad_structuralObjectClass, vals, NULL ) ) {
+               /* Out of memory, do something about it */
+               entry_free( e );
+               *text = "out of memory";
+               return LDAP_OTHER;
        }
 
-       if ( ret != 0 ) {
-           return( ret );
+       BER_BVSTR( &vals[0], "top" );
+       BER_BVSTR( &vals[1], "subentry" );
+       BER_BVSTR( &vals[2], "subschema" );
+       BER_BVSTR( &vals[3], "extensibleObject" );
+       BER_BVZERO( &vals[4] );
+       if ( attr_merge( e, ad_objectClass, vals, NULL ) ) {
+               /* Out of memory, do something about it */
+               entry_free( e );
+               *text = "out of memory";
+               return LDAP_OTHER;
        }
 
-       /* check that each attr in the entry is allowed by some oc */
-       for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-               if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) {
-                       Debug( LDAP_DEBUG_ANY,
-                           "Entry (%s), attr (%s) not allowed\n",
-                           e->e_dn, a->a_type, 0 );
-                       ret = 1;
-               }
-       }
-
-       return( ret );
-}
+       {
+               int rc;
+               AttributeDescription *desc = NULL;
+               struct berval rdn = frontendDB->be_schemadn;
+               vals[0].bv_val = strchr( rdn.bv_val, '=' );
 
-static int
-oc_check_required( Entry *e, char *ocname )
-{
-       struct objclass *oc;
-       int             i;
-       Attribute       *a;
+               if( vals[0].bv_val == NULL ) {
+                       *text = "improperly configured subschema subentry";
+                       return LDAP_OTHER;
+               }
 
-       /* find global oc defn. it we don't know about it assume it's ok */
-       if ( (oc = oc_find( ocname )) == NULL ) {
-               return( 0 );
-       }
+               vals[0].bv_val++;
+               vals[0].bv_len = rdn.bv_len - (vals[0].bv_val - rdn.bv_val);
+               rdn.bv_len -= vals[0].bv_len + 1;
 
-       /* check for empty oc_required */
-       if(oc->oc_required == NULL) {
-               return( 0 );
-       }
+               rc = slap_bv2ad( &rdn, &desc, text );
 
-       /* for each required attribute */
-       for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
-               /* see if it's in the entry */
-               for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-                       if ( strcasecmp( a->a_type, oc->oc_required[i] )
-                           == 0 ) {
-                               break;
-                       }
+               if( rc != LDAP_SUCCESS ) {
+                       entry_free( e );
+                       *text = "improperly configured subschema subentry";
+                       return LDAP_OTHER;
                }
 
-               /* not there => schema violation */
-               if ( a == NULL ) {
-                       return( 1 );
+               nvals[0].bv_val = strchr( frontendDB->be_schemandn.bv_val, '=' );
+               assert( nvals[0].bv_val );
+               nvals[0].bv_val++;
+               nvals[0].bv_len = frontendDB->be_schemandn.bv_len -
+                       (nvals[0].bv_val - frontendDB->be_schemandn.bv_val);
+
+               if ( attr_merge_one( e, desc, vals, nvals ) ) {
+                       /* Out of memory, do something about it */
+                       entry_free( e );
+                       *text = "out of memory";
+                       return LDAP_OTHER;
                }
        }
 
-       return( 0 );
-}
-
-static int
-oc_check_allowed( char *type, struct berval **ocl )
-{
-       struct objclass *oc;
-       int             i, j;
+       {
+               struct          tm *ltm;
+#ifdef HAVE_GMTIME_R
+               struct          tm ltm_buf;
+#endif
+               char            timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
+
+               /*
+                * According to RFC 2251:
+
+   Servers SHOULD provide the attributes createTimestamp and
+   modifyTimestamp in subschema entries, in order to allow clients to
+   maintain their caches of schema information.
+
+                * to be conservative, we declare schema created 
+                * AND modified at server startup time ...
+                */
+
+#ifdef HAVE_GMTIME_R
+               ltm = gmtime_r( &starttime, &ltm_buf );
+#else
+               ldap_pvt_thread_mutex_lock( &gmtime_mutex );
+               ltm = gmtime( &starttime );
+#endif /* HAVE_GMTIME_R */
+               lutil_gentime( timebuf, sizeof(timebuf), ltm );
+#ifndef HAVE_GMTIME_R
+               ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+#endif
 
-       /* always allow objectclass attribute */
-       if ( strcasecmp( type, "objectclass" ) == 0 ) {
-               return( 0 );
-       }
+               vals[0].bv_val = timebuf;
+               vals[0].bv_len = strlen( timebuf );
 
-       /* check that the type appears as req or opt in at least one oc */
-       for ( i = 0; ocl[i] != NULL; i++ ) {
-               /* if we know about the oc */
-               if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) {
-                       /* does it require the type? */
-                       for ( j = 0; oc->oc_required != NULL && 
-                               oc->oc_required[j] != NULL; j++ ) {
-                               if ( strcasecmp( oc->oc_required[j], type )
-                                   == 0 ) {
-                                       return( 0 );
-                               }
-                       }
-                       /* does it allow the type? */
-                       for ( j = 0; oc->oc_allowed != NULL && 
-                               oc->oc_allowed[j] != NULL; j++ ) {
-                               if ( strcasecmp( oc->oc_allowed[j], type )
-                                   == 0 || strcmp( oc->oc_allowed[j], "*" )
-                                   == 0 )
-                               {
-                                       return( 0 );
-                               }
-                       }
-                       /* maybe the next oc allows it */
-
-               /* we don't know about the oc. assume it allows it */
-               } else {
-                       return( 0 );
+               if( attr_merge_one( e, ad_createTimestamp, vals, NULL ) ) {
+                       /* Out of memory, do something about it */
+                       entry_free( e );
+                       *text = "out of memory";
+                       return LDAP_OTHER;
                }
-       }
-
-       /* not allowed by any oc */
-       return( 1 );
-}
-
-static struct objclass *
-oc_find( char *ocname )
-{
-       struct objclass *oc;
-
-       for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
-               if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
-                       return( oc );
+               if( attr_merge_one( e, ad_modifyTimestamp, vals, NULL ) ) {
+                       /* Out of memory, do something about it */
+                       entry_free( e );
+                       *text = "out of memory";
+                       return LDAP_OTHER;
                }
        }
 
-       return( NULL );
-}
-
-#ifdef LDAP_DEBUG
-
-static void
-oc_print( struct objclass *oc )
-{
-       int     i;
-
-       printf( "objectclass %s\n", oc->oc_name );
-       if ( oc->oc_required != NULL ) {
-               printf( "\trequires %s", oc->oc_required[0] );
-               for ( i = 1; oc->oc_required[i] != NULL; i++ ) {
-                       printf( ",%s", oc->oc_required[i] );
-               }
-               printf( "\n" );
-       }
-       if ( oc->oc_allowed != NULL ) {
-               printf( "\tallows %s", oc->oc_allowed[0] );
-               for ( i = 1; oc->oc_allowed[i] != NULL; i++ ) {
-                       printf( ",%s", oc->oc_allowed[i] );
-               }
-               printf( "\n" );
+       if ( syn_schema_info( e ) 
+               || mr_schema_info( e )
+               || mru_schema_info( e )
+               || at_schema_info( e )
+               || oc_schema_info( e )
+               || cr_schema_info( e ) )
+       {
+               /* Out of memory, do something about it */
+               entry_free( e );
+               *text = "out of memory";
+               return LDAP_OTHER;
        }
+       
+       *entry = e;
+       return LDAP_SUCCESS;
 }
-
-#endif