]> git.sur5r.net Git - openldap/commitdiff
DIT content rule code (behind #ifdef)
authorKurt Zeilenga <kurt@openldap.org>
Thu, 10 Oct 2002 03:45:55 +0000 (03:45 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Thu, 10 Oct 2002 03:45:55 +0000 (03:45 +0000)
security simple_bind support
obsolete checks

12 files changed:
servers/slapd/Makefile.in
servers/slapd/backend.c
servers/slapd/compare.c
servers/slapd/config.c
servers/slapd/cr.c [new file with mode: 0644]
servers/slapd/libslapd.dsp
servers/slapd/proto-slap.h
servers/slapd/schema.c
servers/slapd/schema_check.c
servers/slapd/schema_prep.c
servers/slapd/schemaparse.c
servers/slapd/slap.h

index 2176cdcc35807368a119ead166775ff9091fac83..717b91dc7050bdc08269440676b9e01c0c938937 100644 (file)
@@ -9,7 +9,7 @@ XSRCS=version.c
 NT_SRCS = nt_svc.c
 NT_OBJS = nt_svc.o ../../libraries/liblutil/slapdmsg.res
 
-SRCS   = main.c daemon.c connection.c search.c filter.c add.c \
+SRCS   = main.c daemon.c connection.c search.c filter.c add.c cr.c \
                attr.c entry.c config.c backend.c result.c operation.c \
                dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
                value.c ava.c bind.c unbind.c abandon.c filterentry.c \
@@ -22,7 +22,7 @@ SRCS  = main.c daemon.c connection.c search.c filter.c add.c \
                limits.c backglue.c operational.c matchedValues.c \
                $(@PLAT@_SRCS)
 
-OBJS   = main.o daemon.o connection.o search.o filter.o add.o \
+OBJS   = main.o daemon.o connection.o search.o filter.o add.o cr.o \
                attr.o entry.o config.o backend.o result.o operation.o \
                dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
                value.o ava.o bind.o unbind.o abandon.o filterentry.o \
index 23ee665e881f34244c5854335b228144da9c466a..04fac3ccec9825beb554a417f1bb59729d8d1540 100644 (file)
@@ -866,6 +866,15 @@ backend_check_restrictions(
                        return LDAP_CONFIDENTIALITY_REQUIRED;
                }
 
+
+               if( op->o_tag == LDAP_REQ_BIND && opdata == NULL ) {
+                       /* simple bind specific check */
+                       if( op->o_ssf < ssf->sss_simple_bind ) {
+                               *text = "confidentiality required";
+                               return LDAP_CONFIDENTIALITY_REQUIRED;
+                       }
+               }
+
                if( op->o_tag != LDAP_REQ_BIND || opdata == NULL ) {
                        /* these checks don't apply to SASL bind */
 
index 7934821fd4f6e1c4f091df50c388950dce0e44a5..81e3e9f54e206783b54226bbe957f3b67fe4b4fa 100644 (file)
@@ -36,6 +36,7 @@ do_compare(
 )
 {
        Entry *entry = NULL;
+       Entry *fentry = NULL;
        struct berval dn = { 0, NULL };
        struct berval pdn = { 0, NULL };
        struct berval ndn = { 0, NULL };
@@ -169,6 +170,8 @@ do_compare(
                        goto cleanup;
                }
 
+               fentry = entry;
+
        } else if ( bvmatch( &ndn, &global_schemandn ) ) {
 #ifdef NEW_LOGGING
                LDAP_LOG( OPERATION, ARGS, 
@@ -198,11 +201,12 @@ do_compare(
                        rc = 0;
                        goto cleanup;
                }
+               fentry = entry;
        }
 
        if( entry ) {
                rc = compare_entry( conn, op, entry, &ava );
-               entry_free( entry );
+               if( fentry) entry_free( fentry );
 
                send_ldap_result( conn, op, rc, NULL, text, NULL, NULL );
 
index 1f890888ea32be81d1874f5f7c1015c630ffac14..72a9964021a18b6a63935347885345861fdd5397 100644 (file)
@@ -1331,9 +1331,6 @@ read_config( const char *fname, int depth )
                                } else if( strcasecmp( cargv[i], "bind_simple" ) == 0 ) {
                                        disallows |= SLAP_DISALLOW_BIND_SIMPLE;
 
-                               } else if( strcasecmp( cargv[i], "bind_simple_unprotected" ) == 0 ) {
-                                       disallows |= SLAP_DISALLOW_BIND_SIMPLE_UNPROTECTED;
-
                                } else if( strcasecmp( cargv[i], "bind_krbv4" ) == 0 ) {
                                        disallows |= SLAP_DISALLOW_BIND_KRBV4;
 
@@ -1494,6 +1491,12 @@ read_config( const char *fname, int depth )
                                        set->sss_update_sasl =
                                                atoi( &cargv[i][sizeof("update_sasl")] );
 
+                               } else if( strncasecmp( cargv[i], "simple_bind=",
+                                       sizeof("simple_bind") ) == 0 )
+                               {
+                                       set->sss_simple_bind =
+                                               atoi( &cargv[i][sizeof("simple_bind")] );
+
                                } else {
 #ifdef NEW_LOGGING
                                        LDAP_LOG( CONFIG, CRIT, 
@@ -1588,9 +1591,9 @@ read_config( const char *fname, int depth )
 
                /* specify an objectclass */
                } else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
-                       if ( *cargv[1] == '(' ) {
+                       if ( *cargv[1] == '('  /*')'*/) {
                                char * p;
-                               p = strchr(saveline,'(');
+                               p = strchr(saveline,'(' /*')'*/);
                                rc = parse_oc( fname, lineno, p, cargv );
                                if( rc ) return rc;
 
@@ -1606,13 +1609,21 @@ read_config( const char *fname, int depth )
 #endif
                        }
 
+#ifdef SLAP_EXTENDED_SCHEMA
+               } else if ( strcasecmp( cargv[0], "ditcontentrule" ) == 0 ) {
+                       char * p;
+                       p = strchr(saveline,'(' /*')'*/);
+                       rc = parse_cr( fname, lineno, p, cargv );
+                       if( rc ) return rc;
+#endif
+
                /* specify an attribute type */
                } else if (( strcasecmp( cargv[0], "attributetype" ) == 0 )
                        || ( strcasecmp( cargv[0], "attribute" ) == 0 ))
                {
-                       if ( *cargv[1] == '(' ) {
+                       if ( *cargv[1] == '(' /*')'*/) {
                                char * p;
-                               p = strchr(saveline,'(');
+                               p = strchr(saveline,'(' /*')'*/);
                                rc = parse_at( fname, lineno, p, cargv );
                                if( rc ) return rc;
 
diff --git a/servers/slapd/cr.c b/servers/slapd/cr.c
new file mode 100644 (file)
index 0000000..f8f5216
--- /dev/null
@@ -0,0 +1,417 @@
+/* cr.c - content rule routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "ldap_pvt.h"
+
+#ifdef SLAP_EXTENDED_SCHEMA
+
+struct cindexrec {
+       struct berval   cir_name;
+       ContentRule     *cir_cr;
+};
+
+static Avlnode *cr_index = NULL;
+static ContentRule *cr_list = NULL;
+
+static int
+cr_index_cmp(
+    struct cindexrec   *cir1,
+    struct cindexrec   *cir2 )
+{
+       int i = cir1->cir_name.bv_len - cir2->cir_name.bv_len;
+       if (i)
+               return i;
+       return strcasecmp( cir1->cir_name.bv_val, cir2->cir_name.bv_val );
+}
+
+static int
+cr_index_name_cmp(
+    struct berval      *name,
+    struct cindexrec   *cir )
+{
+       int i = name->bv_len - cir->cir_name.bv_len;
+       if (i)
+               return i;
+       return strncasecmp( name->bv_val, cir->cir_name.bv_val, name->bv_len );
+}
+
+ContentRule *
+cr_find( const char *crname )
+{
+       struct berval bv;
+
+       bv.bv_val = (char *)crname;
+       bv.bv_len = strlen( crname );
+
+       return( cr_bvfind( &bv ) );
+}
+
+ContentRule *
+cr_bvfind( struct berval *crname )
+{
+       struct cindexrec        *cir;
+
+       cir = (struct cindexrec *) avl_find( cr_index, crname,
+            (AVL_CMP) cr_index_name_cmp );
+
+       if ( cir != NULL ) {
+               return( cir->cir_cr );
+       }
+
+       return( NULL );
+}
+
+void
+cr_destroy( void )
+{
+       ContentRule *c, *n;
+
+       avl_free(cr_index, ldap_memfree);
+       for (c=cr_list; c; c=n)
+       {
+               n = c->scr_next;
+               if (c->scr_auxiliaries) ldap_memfree(c->scr_auxiliaries);
+               if (c->scr_required) ldap_memfree(c->scr_required);
+               if (c->scr_allowed) ldap_memfree(c->scr_allowed);
+               if (c->scr_precluded) ldap_memfree(c->scr_precluded);
+               ldap_contentrule_free((LDAPContentRule *)c);
+       }
+}
+
+static int
+cr_insert(
+    ContentRule                *scr,
+    const char         **err
+)
+{
+       ContentRule     **crp;
+       struct cindexrec        *cir;
+       char                    **names;
+
+       crp = &cr_list;
+       while ( *crp != NULL ) {
+               crp = &(*crp)->scr_next;
+       }
+       *crp = scr;
+
+       if ( scr->scr_oid ) {
+               cir = (struct cindexrec *)
+                       ch_calloc( 1, sizeof(struct cindexrec) );
+               cir->cir_name.bv_val = scr->scr_oid;
+               cir->cir_name.bv_len = strlen( scr->scr_oid );
+               cir->cir_cr = scr;
+
+               assert( cir->cir_name.bv_val );
+               assert( cir->cir_cr );
+
+               if ( avl_insert( &cr_index, (caddr_t) cir,
+                                (AVL_CMP) cr_index_cmp,
+                                (AVL_DUP) avl_dup_error ) )
+               {
+                       *err = scr->scr_oid;
+                       ldap_memfree(cir);
+                       return SLAP_SCHERR_CR_DUP;
+               }
+
+               /* FIX: temporal consistency check */
+               assert( cr_bvfind(&cir->cir_name) != NULL );
+       }
+
+       if ( (names = scr->scr_names) ) {
+               while ( *names ) {
+                       cir = (struct cindexrec *)
+                               ch_calloc( 1, sizeof(struct cindexrec) );
+                       cir->cir_name.bv_val = *names;
+                       cir->cir_name.bv_len = strlen( *names );
+                       cir->cir_cr = scr;
+
+                       assert( cir->cir_name.bv_val );
+                       assert( cir->cir_cr );
+
+                       if ( avl_insert( &cr_index, (caddr_t) cir,
+                                        (AVL_CMP) cr_index_cmp,
+                                        (AVL_DUP) avl_dup_error ) )
+                       {
+                               *err = *names;
+                               ldap_memfree(cir);
+                               return SLAP_SCHERR_CR_DUP;
+                       }
+
+                       /* FIX: temporal consistency check */
+                       assert( cr_bvfind(&cir->cir_name) != NULL );
+
+                       names++;
+               }
+       }
+
+       return 0;
+}
+
+static int
+cr_add_auxiliaries(
+    ContentRule                *scr,
+       int                     *op,
+    const char         **err )
+{
+       int naux;
+
+       if( scr->scr_oc_oids_aux == NULL ) return 0;
+       
+       for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
+               /* count them */ ;
+       }
+
+       scr->scr_auxiliaries = ch_calloc( naux+1, sizeof(ObjectClass *));
+
+       for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
+               ObjectClass *soc = scr->scr_auxiliaries[naux]
+                       = oc_find(scr->scr_oc_oids_aux[naux]);
+               if ( !soc ) {
+                       *err = scr->scr_oc_oids_aux[naux];
+                       return SLAP_SCHERR_CLASS_NOT_FOUND;
+               }
+
+               if( soc->soc_flags & SLAP_OC_OPERATIONAL ) (*op)++;
+
+               if( soc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
+                       *err = scr->scr_oc_oids_aux[naux];
+                       return SLAP_SCHERR_CR_BAD_AUX;
+               }
+       }
+
+       scr->scr_auxiliaries[naux] = NULL;
+
+       return 0;
+}
+
+static int
+cr_create_required(
+    ContentRule                *scr,
+       int                     *op,
+    const char         **err )
+{
+    char               **attrs = scr->scr_at_oids_must;
+       char            **attrs1;
+       AttributeType   *sat;
+
+       if ( attrs ) {
+               attrs1 = attrs;
+               while ( *attrs1 ) {
+                       sat = at_find(*attrs1);
+                       if ( !sat ) {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_ATTR_NOT_FOUND;
+                       }
+
+                       if( is_at_operational( sat )) (*op)++;
+
+                       if ( at_find_in_list(sat, scr->scr_required) < 0) {
+                               if ( at_append_to_list(sat, &scr->scr_required) ) {
+                                       *err = *attrs1;
+                                       return SLAP_SCHERR_OUTOFMEM;
+                               }
+                       } else {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_CR_BAD_AT;
+                       }
+                       attrs1++;
+               }
+       }
+       return 0;
+}
+
+static int
+cr_create_allowed(
+    ContentRule                *scr,
+       int                     *op,
+    const char         **err )
+{
+    char               **attrs = scr->scr_at_oids_may;
+       char            **attrs1;
+       AttributeType   *sat;
+
+       if ( attrs ) {
+               attrs1 = attrs;
+               while ( *attrs1 ) {
+                       sat = at_find(*attrs1);
+                       if ( !sat ) {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_ATTR_NOT_FOUND;
+                       }
+
+                       if( is_at_operational( sat )) (*op)++;
+
+                       if ( at_find_in_list(sat, scr->scr_required) < 0 &&
+                               at_find_in_list(sat, scr->scr_allowed) < 0 )
+                       {
+                               if ( at_append_to_list(sat, &scr->scr_allowed) ) {
+                                       *err = *attrs1;
+                                       return SLAP_SCHERR_OUTOFMEM;
+                               }
+                       } else {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_CR_BAD_AT;
+                       }
+                       attrs1++;
+               }
+       }
+       return 0;
+}
+
+static int
+cr_create_precluded(
+    ContentRule                *scr,
+       int                     *op,
+    const char         **err )
+{
+    char               **attrs = scr->scr_at_oids_not;
+       char            **attrs1;
+       AttributeType   *sat;
+
+       if ( attrs ) {
+               attrs1 = attrs;
+               while ( *attrs1 ) {
+                       sat = at_find(*attrs1);
+                       if ( !sat ) {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_ATTR_NOT_FOUND;
+                       }
+
+                       if( is_at_operational( sat )) (*op)++;
+
+                       /* FIXME: should also make sure attribute type is not
+                               a required attribute of the structural class or
+                               any auxiliary class */
+                       if ( at_find_in_list(sat, scr->scr_required) < 0 &&
+                               at_find_in_list(sat, scr->scr_allowed) < 0 &&
+                               at_find_in_list(sat, scr->scr_precluded) < 0 )
+                       {
+                               if ( at_append_to_list(sat, &scr->scr_precluded) ) {
+                                       *err = *attrs1;
+                                       return SLAP_SCHERR_OUTOFMEM;
+                               }
+                       } else {
+                               *err = *attrs1;
+                               return SLAP_SCHERR_CR_BAD_AT;
+                       }
+                       attrs1++;
+               }
+       }
+       return 0;
+}
+
+int
+cr_add(
+    LDAPContentRule    *cr,
+       int user,
+    const char         **err
+)
+{
+       ContentRule     *scr;
+       int             code;
+       int             op = 0;
+
+       if ( cr->cr_names != NULL ) {
+               int i;
+
+               for( i=0; cr->cr_names[i]; i++ ) {
+                       if( !slap_valid_descr( cr->cr_names[i] ) ) {
+                               return SLAP_SCHERR_BAD_DESCR;
+                       }
+               }
+       }
+
+       if ( !OID_LEADCHAR( cr->cr_oid[0] )) {
+               /* Expand OID macros */
+               char *oid = oidm_find( cr->cr_oid );
+               if ( !oid ) {
+                       *err = cr->cr_oid;
+                       return SLAP_SCHERR_OIDM;
+               }
+               if ( oid != cr->cr_oid ) {
+                       ldap_memfree( cr->cr_oid );
+                       cr->cr_oid = oid;
+               }
+       }
+
+       scr = (ContentRule *) ch_calloc( 1, sizeof(ContentRule) );
+       AC_MEMCPY( &scr->scr_crule, cr, sizeof(LDAPContentRule) );
+
+       scr->scr_sclass = oc_find(cr->cr_oid);
+       if ( !scr->scr_sclass ) {
+               *err = cr->cr_oid;
+               return SLAP_SCHERR_CLASS_NOT_FOUND;
+       }
+
+       /* check object class usage */
+       if( scr->scr_sclass->soc_kind != LDAP_SCHEMA_STRUCTURAL )
+       {
+               *err = cr->cr_oid;
+               return SLAP_SCHERR_CR_BAD_STRUCT;
+       }
+
+       if( scr->scr_sclass->soc_flags & SLAP_OC_OPERATIONAL ) op++;
+
+       code = cr_add_auxiliaries( scr, &op, err );
+       if ( code != 0 ) return code;
+
+       code = cr_create_required( scr, &op, err );
+       if ( code != 0 ) return code;
+
+       code = cr_create_allowed( scr, &op, err );
+       if ( code != 0 ) return code;
+
+       code = cr_create_precluded( scr, &op, err );
+       if ( code != 0 ) return code;
+
+       if( user && op ) return SLAP_SCHERR_CR_BAD_AUX;
+
+       code = cr_insert(scr,err);
+       return code;
+}
+
+#endif
+
+int
+cr_schema_info( Entry *e )
+{
+#ifdef SLAP_EXTENDED_SCHEMA
+       struct berval   vals[2];
+       ContentRule     *cr;
+
+       AttributeDescription *ad_ditContentRules = slap_schema.si_ad_ditContentRules;
+
+       vals[1].bv_val = NULL;
+
+       for ( cr = cr_list; cr; cr = cr->scr_next ) {
+               if ( ldap_contentrule2bv( &cr->scr_crule, vals ) == NULL ) {
+                       return -1;
+               }
+
+#if 0
+               if( cr->scr_flags & SLAP_CR_HIDE ) continue;
+#endif
+
+#if 0
+               Debug( LDAP_DEBUG_TRACE, "Merging cr [%ld] %s\n",
+              (long) vals[0].bv_len, vals[0].bv_val, 0 );
+#endif
+               attr_merge( e, ad_ditContentRules, vals );
+               ldap_memfree( vals[0].bv_val );
+       }
+#endif
+       return 0;
+}
index 41614b649119c930c80c6244fef22116756e1592..9920e800dfb6c0689dbd0e2f86c58580e27fb643 100644 (file)
@@ -192,6 +192,10 @@ SOURCE=.\controls.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\cr.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\daemon.c
 # End Source File
 # Begin Source File
index 74f2b2655b452d6d5ca8668efd75d69b4f49fb42..d7a963ed1b5d193ab3aa98a58d810a1e1b5a9bf0 100644 (file)
@@ -312,6 +312,22 @@ LDAP_SLAPD_F (void) connection_done LDAP_P((Connection *));
 
 LDAP_SLAPD_F (void) connection2anonymous LDAP_P((Connection *));
 
+/*
+ * cr.c
+ */
+LDAP_SLAPD_F (int) cr_schema_info( Entry *e );
+
+LDAP_SLAPD_F (int) cr_add LDAP_P((
+       LDAPContentRule *oc,
+       int user,
+       const char **err));
+LDAP_SLAPD_F (void) cr_destroy LDAP_P(( void ));
+
+LDAP_SLAPD_F (ContentRule *) cr_find LDAP_P((
+       const char *crname));
+LDAP_SLAPD_F (ContentRule *) cr_bvfind LDAP_P((
+       struct berval *crname));
+
 /*
  * daemon.c
  */
@@ -954,8 +970,8 @@ LDAP_SLAPD_F (int) slap_schema_check LDAP_P((void));
  */
 LDAP_SLAPD_F( int ) slap_valid_descr( const char * );
 
-LDAP_SLAPD_F (int) parse_oc_old LDAP_P((
-       Backend *be, const char *fname, int lineno, int argc, char **argv ));
+LDAP_SLAPD_F (int) parse_cr LDAP_P((
+       const char *fname, int lineno, char *line, char **argv ));
 LDAP_SLAPD_F (int) parse_oc LDAP_P((
        const char *fname, int lineno, char *line, char **argv ));
 LDAP_SLAPD_F (int) parse_at LDAP_P((
index bc218fcca8dc71afa47c3549d8fa4a6fba9607d7..c9d4436e8bc12f7da86f7cb4b8b8801cc9d2523e 100644 (file)
@@ -115,7 +115,8 @@ schema_info( Entry **entry, const char **text )
                || mr_schema_info( e )
                || mru_schema_info( e )
                || at_schema_info( e )
-               || oc_schema_info( e ) )
+               || oc_schema_info( e )
+               || cr_schema_info( e ) )
        {
                /* Out of memory, do something about it */
                entry_free( e );
index f9b4e082b81b690043eede1969429e70382a8b6f..737a0eb4a1be45ed148cbbf24a362d2d776373e4 100644 (file)
@@ -38,6 +38,10 @@ entry_schema_check(
 {
        Attribute       *a, *asc, *aoc;
        ObjectClass *sc, *oc;
+#ifdef SLAP_EXTENDED_SCHEMA
+       AttributeType *at;
+       ContentRule *cr;
+#endif
        int     rc, i;
        struct berval nsc;
        AttributeDescription *ad_structuralObjectClass
@@ -49,7 +53,9 @@ entry_schema_check(
        int collectiveSubentry = 0;
 
 #if 0
-       if( subentry) collectiveSubentry = is_entry_collectiveAttributeSubentry( e );
+       if( subentry ) {
+               collectiveSubentry = is_entry_collectiveAttributeSubentry( e );
+       }
 #endif
 
        *text = textbuf;
@@ -157,6 +163,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 ) {
@@ -196,6 +219,92 @@ entry_schema_check(
                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 ) {
+               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 ) {
+                               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->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 */
        for ( i = 0; aoc->a_vals[i].bv_val != NULL; i++ ) {
                if ( (oc = oc_bvfind( &aoc->a_vals[i] )) == NULL ) {
@@ -203,6 +312,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 );
@@ -286,8 +413,46 @@ entry_schema_check(
                        }
 
                } 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) {
                                snprintf( textbuf, textlen, 
                                        "object class '%s' requires attribute '%s'",
@@ -317,7 +482,35 @@ entry_schema_check(
 
        /* check that each attr in the entry is allowed by some oc */
        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 ) {
                        char *type = a->a_desc->ad_cname.bv_val;
 
index 7625eefed1fad8bdafb27c81eaeaf0cc6aee3b6c..d50649f85ef720ea579acdf3a5b87939a816e83a 100644 (file)
@@ -301,7 +301,7 @@ static struct slap_schema_oc_map {
                        "SUP top STRUCTURAL MAY cn )",
                rootDseObjectClass, SLAP_OC_OPERATIONAL,
                offsetof(struct slap_internal_schema, si_oc_rootdse) },
-       { "subentry", "( 2.5.20.0 NAME 'subentry' "
+       { "subentry", "( 2.5.17.0 NAME 'subentry' "
                        "SUP top STRUCTURAL "
                        "MUST ( cn $ subtreeSpecification ) )",
                subentryObjectClass, SLAP_OC_SUBENTRY|SLAP_OC_OPERATIONAL,
index cb5fca8f82d05f7f792ed66f1593ad4f05594dfc..d0aca20d90b8d6f7d89035e1328f587714387d4e 100644 (file)
@@ -42,7 +42,11 @@ static char *const err2text[] = {
        "OID or name required",
        "Qualifier not supported",
        "Invalid NAME",
-       "OID could not be expanded"
+       "OID could not be expanded",
+       "Duplicate Content Rule",
+       "Content Rule not for STRUCTURAL object class",
+       "Content Rule AUX contains non-AUXILIARY object class"
+       "Content Rule attribute type list contains duplicate"
 };
 
 char *
@@ -92,6 +96,64 @@ dscompare(const char *s1, const char *s2, char delim)
        return 0;
 }
 
+#ifdef SLAP_EXTENDED_SCHEMA
+
+static void
+cr_usage( void )
+{
+       fprintf( stderr,
+               "DITContentRuleDescription = \"(\" whsp\n"
+               "  numericoid whsp       ; StructuralObjectClass identifier\n"
+               "  [ \"NAME\" qdescrs ]\n"
+               "  [ \"DESC\" qdstring ]\n"
+               "  [ \"OBSOLETE\" whsp ]\n"
+               "  [ \"AUX\" oids ]      ; Auxiliary ObjectClasses\n"
+               "  [ \"MUST\" oids ]     ; AttributeTypes\n"
+               "  [ \"MAY\" oids ]      ; AttributeTypes\n"
+               "  [ \"NOT\" oids ]      ; AttributeTypes\n"
+               "  whsp \")\"\n" );
+}
+
+int
+parse_cr(
+    const char *fname,
+    int                lineno,
+    char       *line,
+    char       **argv
+)
+{
+       LDAPContentRule *cr;
+       int             code;
+       const char      *err;
+
+       cr = ldap_str2contentrule(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
+       if ( !cr ) {
+               fprintf( stderr, "%s: line %d: %s before %s\n",
+                        fname, lineno, ldap_scherr2str(code), err );
+               cr_usage();
+               return 1;
+       }
+
+       if ( cr->cr_oid == NULL ) {
+               fprintf( stderr,
+                       "%s: line %d: Content rule has no OID\n",
+                       fname, lineno );
+               cr_usage();
+               return 1;
+       }
+
+       code = cr_add(cr,1,&err);
+       if ( code ) {
+               fprintf( stderr, "%s: line %d: %s: \"%s\"\n",
+                        fname, lineno, scherr2str(code), err);
+               return 1;
+       }
+
+       ldap_memfree(cr);
+       return 0;
+}
+
+#endif
 
 int
 parse_oc(
@@ -149,7 +211,6 @@ oc_usage( void )
                "  whsp \")\"\n" );
 }
 
-
 static void
 at_usage( void )
 {
index fc3eb5e8cf6c95b30f4a39e5f6379f0c986d73d1..055ffa6323341046e725ed98f510815c3282df6a 100644 (file)
@@ -35,6 +35,8 @@
 #include "ldap_pvt_thread.h"
 #include "ldap_queue.h"
 
+#define SLAP_EXTENDED_SCHEMA 1
+
 LDAP_BEGIN_DECL
 /*
  * SLAPD Memory allocation macros
@@ -164,6 +166,7 @@ typedef struct slap_ssf_set {
        slap_ssf_t sss_update_transport;
        slap_ssf_t sss_update_tls;
        slap_ssf_t sss_update_sasl;
+       slap_ssf_t sss_simple_bind;
 } slap_ssf_set_t;
 
 /*
@@ -211,9 +214,11 @@ typedef struct slap_ssf_set {
 #define SLAP_INDEX_SUBSTR_FINAL_PREFIX '$'
 #define SLAP_INDEX_CONT_PREFIX         '.'             /* prefix for continuation keys */
 
-#define SLAP_SYNTAX_MATCHINGRULES_OID  "1.3.6.1.4.1.1466.115.121.1.30"
-#define SLAP_SYNTAX_ATTRIBUTETYPES_OID "1.3.6.1.4.1.1466.115.121.1.3"
-#define SLAP_SYNTAX_OBJECTCLASSES_OID  "1.3.6.1.4.1.1466.115.121.1.37"
+#define SLAP_SYNTAX_MATCHINGRULES_OID   "1.3.6.1.4.1.1466.115.121.1.30"
+#define SLAP_SYNTAX_ATTRIBUTETYPES_OID  "1.3.6.1.4.1.1466.115.121.1.3"
+#define SLAP_SYNTAX_OBJECTCLASSES_OID   "1.3.6.1.4.1.1466.115.121.1.37"
+#define SLAP_SYNTAX_MATCHINGRULEUSES_OID "1.3.6.1.4.1.1466.115.121.1.31"
+#define SLAP_SYNTAX_CONTENTRULE_OID             "1.3.6.1.4.1.1466.115.121.1.16"
 
 #ifdef LDAP_CLIENT_UPDATE
 #define LCUP_COOKIE_OID "1.3.6.1.4.1.4203.666.10.1"
@@ -242,7 +247,11 @@ typedef struct slap_ssf_set {
 #define SLAP_SCHERR_NOT_SUPPORTED              18
 #define SLAP_SCHERR_BAD_DESCR                  19
 #define SLAP_SCHERR_OIDM                               20
-#define SLAP_SCHERR_LAST                               SLAP_SCHERR_OIDM
+#define SLAP_SCHERR_CR_DUP                             21
+#define SLAP_SCHERR_CR_BAD_STRUCT              22
+#define SLAP_SCHERR_CR_BAD_AUX                 23
+#define SLAP_SCHERR_CR_BAD_AT                  24
+#define SLAP_SCHERR_LAST                               SLAP_SCHERR_CR_BAD_AT
 
 typedef union slap_sockaddr {
        struct sockaddr sa_addr;
@@ -590,7 +599,6 @@ typedef struct slap_object_class {
 #define SLAP_OC_OPERATIONAL    0x4000
 #define SLAP_OC_HIDE           0x8000
 
-#ifdef LDAP_EXTENDED_SCHEMA
 /*
  * DIT content rule
  */
@@ -601,16 +609,17 @@ typedef struct slap_content_rule {
        AttributeType           **scr_required;         /* optional */
        AttributeType           **scr_allowed;          /* optional */
        AttributeType           **scr_precluded;        /* optional */
-#define scr_oid                        scr_crule.cr_oid
-#define scr_names              scr_crule.cr_names
-#define scr_desc               scr_crule.cr_desc
-#define scr_obsolete           soc_oclass.cr_obsolete
-#define scr_cr_oids_aux                soc_oclass.cr_oc_oids_aux
-#define scr_cr_oids_must       soc_oclass.cr_at_oids_must
-#define scr_cr_oids_may                soc_oclass.cr_at_oids_may
-#define scr_cr_oids_not                soc_oclass.cr_at_oids_not
+#define scr_oid                                scr_crule.cr_oid
+#define scr_names                      scr_crule.cr_names
+#define scr_desc                       scr_crule.cr_desc
+#define scr_obsolete           scr_crule.cr_obsolete
+#define scr_oc_oids_aux                scr_crule.cr_oc_oids_aux
+#define scr_at_oids_must       scr_crule.cr_at_oids_must
+#define scr_at_oids_may                scr_crule.cr_at_oids_may
+#define scr_at_oids_not                scr_crule.cr_at_oids_not
+
+       struct slap_content_rule *scr_next;
 } ContentRule;
-#endif
 
 /*
  * represents a recognized attribute description ( type + options )
@@ -1255,6 +1264,8 @@ struct slap_backend_db {
 #define SLAP_DISALLOW_TLS_2_ANON       0x0010U /* StartTLS -> Anonymous */
 #define SLAP_DISALLOW_TLS_AUTHC                0x0020U /* TLS while authenticated */
 
+#define SLAP_DISALLOW_AUX_WO_CR                0x4000U
+
        slap_mask_t     be_requires;    /* pre-operation requirements */
 #define SLAP_REQUIRE_BIND              0x0001U /* bind before op */
 #define SLAP_REQUIRE_LDAP_V3   0x0002U /* LDAPv3 before op */