Basic framework for DIT Content Rules (not yet enforced)

This commit is contained in:
Kurt Zeilenga 2002-10-09 07:11:50 +00:00
parent cf318d2340
commit acc32b9d9e
11 changed files with 547 additions and 55 deletions

View 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 \

View file

@ -591,12 +591,12 @@ at_schema_info( Entry *e )
vals[1].bv_val = NULL;
for ( at = attr_list; at; at = at->sat_next ) {
if( at->sat_flags & SLAP_AT_HIDE ) continue;
if ( ldap_attributetype2bv( &at->sat_atype, vals ) == NULL ) {
return -1;
}
if( at->sat_flags & SLAP_AT_HIDE ) continue;
attr_merge( e, ad_attributeTypes, vals );
ldap_memfree( vals[0].bv_val );
}

View 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 );

View file

@ -1577,9 +1577,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;
@ -1595,13 +1595,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;

417
servers/slapd/cr.c Normal file
View file

@ -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;
}

View 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

View file

@ -465,31 +465,6 @@ oc_add(
return code;
}
#ifdef LDAP_DEBUG
static void
oc_print( ObjectClass *oc )
{
int i;
const char *mid;
printf( "objectclass %s\n", ldap_objectclass2name( &oc->soc_oclass ) );
if ( oc->soc_required != NULL ) {
mid = "\trequires ";
for ( i = 0; oc->soc_required[i] != NULL; i++, mid = "," )
printf( "%s%s", mid,
ldap_attributetype2name( &oc->soc_required[i]->sat_atype ) );
printf( "\n" );
}
if ( oc->soc_allowed != NULL ) {
mid = "\tallows ";
for ( i = 0; oc->soc_allowed[i] != NULL; i++, mid = "," )
printf( "%s%s", mid,
ldap_attributetype2name( &oc->soc_allowed[i]->sat_atype ) );
printf( "\n" );
}
}
#endif
int
oc_schema_info( Entry *e )
{
@ -501,12 +476,12 @@ oc_schema_info( Entry *e )
vals[1].bv_val = NULL;
for ( oc = oc_list; oc; oc = oc->soc_next ) {
if( oc->soc_flags & SLAP_OC_HIDE ) continue;
if ( ldap_objectclass2bv( &oc->soc_oclass, vals ) == NULL ) {
return -1;
}
if( oc->soc_flags & SLAP_OC_HIDE ) continue;
#if 0
Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n",
(long) vals[0].bv_len, vals[0].bv_val, 0 );

View 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((

View 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 );

View 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 )
{

View file

@ -212,9 +212,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"
@ -243,7 +245,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;
@ -591,7 +597,6 @@ typedef struct slap_object_class {
#define SLAP_OC_OPERATIONAL 0x4000
#define SLAP_OC_HIDE 0x8000
#ifdef LDAP_EXTENDED_SCHEMA
/*
* DIT content rule
*/
@ -602,16 +607,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 )