First step in new schema support.

This commit is contained in:
Julio Sánchez Fernández 1999-05-28 14:27:07 +00:00
parent 8c954245fd
commit 7f357399cf
8 changed files with 852 additions and 109 deletions

View File

@ -22,6 +22,10 @@
#include "slap.h"
#ifdef LDAP_DEBUG
static void at_index_print( void );
#endif
void
attr_free( Attribute *a )
{
@ -174,11 +178,11 @@ attr_delete(
#define DEFAULT_SYNTAX SYNTAX_CIS
/* Force compilation errors by commenting out this
struct asyntaxinfo {
char **asi_names;
int asi_syntax;
};
static Avlnode *attr_syntaxes = NULL;
static int
@ -228,6 +232,8 @@ attr_syntax_dup(
return( 1 );
}
*/
/*
* attr_syntax - return the syntax of attribute type
*/
@ -235,14 +241,11 @@ attr_syntax_dup(
int
attr_syntax( char *type )
{
struct asyntaxinfo *asi = NULL;
AttributeType *sat;
if ( (asi = (struct asyntaxinfo *) avl_find( attr_syntaxes, type,
(AVL_CMP) attr_syntax_name_cmp )) != NULL ||
(asi = (struct asyntaxinfo *) avl_find_lin( attr_syntaxes, type,
(AVL_CMP) attr_syntax_names_cmp )) != NULL )
{
return( asi->asi_syntax );
sat = at_find(type);
if ( sat ) {
return( sat->sat_syntax_compat );
}
return( DEFAULT_SYNTAX );
@ -261,8 +264,10 @@ attr_syntax_config(
)
{
char *save;
struct asyntaxinfo *a;
LDAP_ATTRIBUTE_TYPE *at;
int lasti;
int code;
char *err;
if ( argc < 2 ) {
Debug( LDAP_DEBUG_ANY,
@ -271,23 +276,30 @@ attr_syntax_config(
return;
}
a = (struct asyntaxinfo *) ch_calloc( 1, sizeof(struct asyntaxinfo) );
at = (LDAP_ATTRIBUTE_TYPE *)
ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) );
lasti = argc - 1;
if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 ||
strcasecmp( argv[lasti], "cis" ) == 0 ) {
a->asi_syntax = SYNTAX_CIS;
at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
at->at_equality_oid = "2.5.13.2";
} else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
strcasecmp( argv[lasti], "tel" ) == 0 ) {
a->asi_syntax = (SYNTAX_CIS | SYNTAX_TEL);
at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.50";
at->at_equality_oid = "2.5.13.20";
} else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
a->asi_syntax = (SYNTAX_CIS | SYNTAX_DN);
at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.12";
at->at_equality_oid = "2.5.13.1";
} else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
strcasecmp( argv[lasti], "ces" ) == 0 ) {
a->asi_syntax = SYNTAX_CES;
at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
/* notice: this is caseExactIA5Match */
at->at_equality_oid = "1.3.6.1.4.1.1466.109.114.1";
} else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
strcasecmp( argv[lasti], "bin" ) == 0 ) {
a->asi_syntax = SYNTAX_BIN;
at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.5";
/* There is no match for binary syntax. Really */
} else {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
@ -295,50 +307,292 @@ attr_syntax_config(
Debug( LDAP_DEBUG_ANY,
"possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
0, 0, 0 );
free( (char *) a );
free( (AttributeType *) at );
return;
}
save = argv[lasti];
argv[lasti] = NULL;
a->asi_names = charray_dup( argv );
at->at_names = charray_dup( argv );
argv[lasti] = save;
switch ( avl_insert( &attr_syntaxes, (caddr_t) a,
(AVL_CMP) attr_syntax_cmp,
(AVL_DUP) attr_syntax_dup ) ) {
case -1: /* duplicate - different syntaxes */
Debug( LDAP_DEBUG_ARGS, "%s: line %d: duplicate attribute\n",
fname, lineno, 0 );
/* FALL */
case 1: /* duplicate - same syntaxes */
charray_free( a->asi_names );
free( (char *) a );
break;
default: /* inserted */
break;
code = at_add( at, &err );
if ( code ) {
fprintf( stderr, "%s: line %d: %s %s\n",
fname, lineno, scherr2str(code), err);
exit( 1 );
}
ldap_memfree(at);
}
int
at_fake_if_needed(
char *name
)
{
char *argv[3];
if ( at_find( name ) ) {
return 0;
} else {
argv[0] = name;
argv[1] = "cis";
argv[2] = NULL;
attr_syntax_config( "implicit", 0, 2, argv );
return 0;
}
}
struct aindexrec {
char *air_name;
AttributeType *air_at;
};
static Avlnode *attr_index = NULL;
static AttributeType *attr_list = NULL;
static int
attr_index_cmp(
struct aindexrec *air1,
struct aindexrec *air2
)
{
return (strcasecmp( air1->air_name, air2->air_name ));
}
static int
attr_index_name_cmp(
char *type,
struct aindexrec *air
)
{
return (strcasecmp( type, air->air_name ));
}
AttributeType *
at_find(
char *name
)
{
struct aindexrec *air = NULL;
if ( (air = (struct aindexrec *) avl_find( attr_index, name,
(AVL_CMP) attr_index_name_cmp )) != NULL ) {
return( air->air_at );
}
return( NULL );
}
int
at_append_to_list(
AttributeType *sat,
AttributeType ***listp
)
{
AttributeType **list;
AttributeType **list1;
int size;
list = *listp;
if ( !list ) {
size = 2;
list = calloc(size, sizeof(AttributeType *));
if ( !list ) {
return -1;
}
} else {
size = 0;
list1 = *listp;
while ( *list1 ) {
size++;
list1++;
}
size += 2;
list1 = realloc(list, size*sizeof(AttributeType *));
if ( !list1 ) {
return -1;
}
list = list1;
}
list[size-2] = sat;
list[size-1] = NULL;
*listp = list;
return 0;
}
int
at_delete_from_list(
int pos,
AttributeType ***listp
)
{
AttributeType **list;
AttributeType **list1;
int i;
int j;
if ( pos < 0 ) {
return -2;
}
list = *listp;
for ( i=0; list[i]; i++ )
;
if ( pos >= i ) {
return -2;
}
for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
list[i] = list[j];
}
list[i] = NULL;
/* Tell the runtime this can be shrinked */
list1 = realloc(list, (i+1)*sizeof(AttributeType **));
if ( !list1 ) {
return -1;
}
*listp = list1;
return 0;
}
int
at_find_in_list(
AttributeType *sat,
AttributeType **list
)
{
int i;
if ( !list ) {
return -1;
}
for ( i=0; list[i]; i++ ) {
if ( sat == list[i] ) {
return i;
}
}
return -1;
}
static int
at_insert(
AttributeType *sat,
char **err
)
{
AttributeType **atp;
struct aindexrec *air;
char **names;
atp = &attr_list;
while ( *atp != NULL ) {
atp = &(*atp)->sat_next;
}
*atp = sat;
if ( sat->sat_atype.at_oid ) {
air = (struct aindexrec *)
ch_calloc( 1, sizeof(struct aindexrec) );
air->air_name = sat->sat_atype.at_oid;
air->air_at = sat;
if ( avl_insert( &attr_index, (caddr_t) air,
(AVL_CMP) attr_index_cmp,
(AVL_DUP) avl_dup_error ) ) {
*err = sat->sat_atype.at_oid;
ldap_memfree(air);
return SLAP_SCHERR_DUP_ATTR;
}
/* FIX: temporal consistency check */
at_find(air->air_name);
}
if ( (names = sat->sat_atype.at_names) ) {
while ( *names ) {
air = (struct aindexrec *)
ch_calloc( 1, sizeof(struct aindexrec) );
air->air_name = ch_strdup(*names);
air->air_at = sat;
if ( avl_insert( &attr_index, (caddr_t) air,
(AVL_CMP) attr_index_cmp,
(AVL_DUP) avl_dup_error ) ) {
*err = *names;
ldap_memfree(air);
return SLAP_SCHERR_DUP_ATTR;
}
/* FIX: temporal consistency check */
at_find(air->air_name);
names++;
}
}
return 0;
}
int
at_add(
LDAP_ATTRIBUTE_TYPE *at,
char **err
)
{
AttributeType *sat;
AttributeType *sat1;
int code;
char *errattr;
if ( at->at_names && at->at_names[0] ) {
errattr = at->at_names[0];
} else {
errattr = at->at_oid;
}
sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE));
if ( at->at_sup_oid ) {
if ( (sat1 = at_find(at->at_sup_oid)) ) {
sat->sat_sup = sat1;
if ( at_append_to_list(sat, &sat1->sat_subtypes) ) {
*err = errattr;
return SLAP_SCHERR_OUTOFMEM;
}
} else {
*err = errattr;
return SLAP_SCHERR_ATTR_NOT_FOUND;
}
}
if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.15") ) {
if ( !strcmp(at->at_equality_oid,
"1.3.6.1.4.1.1466.109.114.1") ) {
sat->sat_syntax_compat = SYNTAX_CES;
} else {
sat->sat_syntax_compat = SYNTAX_CIS;
}
} else if ( !strcmp(at->at_syntax_oid,
"1.3.6.1.4.1.1466.115.121.1.50") ) {
sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL;
} else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.12") ) {
sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN;
} else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) {
sat->sat_syntax_compat = SYNTAX_BIN;
} else {
sat->sat_syntax_compat = DEFAULT_SYNTAX;
}
code = at_insert(sat,err);
return code;
}
#ifdef LDAP_DEBUG
static int
attr_syntax_printnode( struct asyntaxinfo *a )
at_index_printnode( struct aindexrec *air )
{
int i;
printf( "syntax: 0x%x\n", a->asi_syntax );
for ( i = 0; a->asi_names[i] != NULL; i++ ) {
printf( " name: %s\n", a->asi_names[i] );
}
printf( "%s = %s\n", air->air_name, ldap_attributetype2str(&air->air_at->sat_atype) );
return( 0 );
}
static void
attr_syntax_print( void )
at_index_print( void )
{
(void) avl_apply( attr_syntaxes, (AVL_APPLY) attr_syntax_printnode,
printf("Printing attribute type index:\n");
(void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode,
0, -1, AVL_INORDER );
}

View File

@ -150,10 +150,12 @@ bdb2i_back_db_init_internal(
li->li_directory = DEFAULT_DB_DIRECTORY;
/* always index dn, id2children, objectclass (used in some searches) */
argv[ 0 ] = "dn";
argv[ 1 ] = "dn";
argv[ 2 ] = NULL;
attr_syntax_config( "ldbm dn initialization", 0, 2, argv );
if ( !at_find( "dn" ) ) {
argv[ 0 ] = "dn";
argv[ 1 ] = "dn";
argv[ 2 ] = NULL;
attr_syntax_config( "ldbm dn initialization", 0, 2, argv );
}
argv[ 0 ] = "dn";
argv[ 1 ] = "sub";
argv[ 2 ] = "eq";

View File

@ -110,10 +110,12 @@ ldbm_back_db_init(
li->li_directory = ch_strdup( DEFAULT_DB_DIRECTORY );
/* always index dn, id2children, objectclass (used in some searches) */
argv[ 0 ] = "dn";
argv[ 1 ] = "dn";
argv[ 2 ] = NULL;
attr_syntax_config( "ldbm dn initialization", 0, 2, argv );
if ( !at_find( "dn" ) ) {
argv[ 0 ] = "dn";
argv[ 1 ] = "dn";
argv[ 2 ] = NULL;
attr_syntax_config( "ldbm dn initialization", 0, 2, argv );
}
argv[ 0 ] = "dn";
argv[ 1 ] = "sub";
argv[ 2 ] = "eq";

View File

@ -346,12 +346,24 @@ read_config( char *fname )
#endif
/* specify an objectclass */
} else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
parse_oc( be, fname, lineno, cargc, cargv );
if ( *cargv[1] == '(' ) {
char * p;
p = strchr(line,'(');
parse_oc( fname, lineno, p );
} else {
parse_oc_old( be, fname, lineno, cargc, cargv );
}
/* specify an attribute */
} else if ( strcasecmp( cargv[0], "attribute" ) == 0 ) {
attr_syntax_config( fname, lineno, cargc - 1,
&cargv[1] );
if ( *cargv[1] == '(' ) {
char * p;
p = strchr(line,'(');
parse_at( fname, lineno, p );
} else {
attr_syntax_config( fname, lineno, cargc - 1,
&cargv[1] );
}
/* turn on/off schema checking */
} else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {

View File

@ -46,6 +46,11 @@ Attribute * attr_find LDAP_P(( Attribute *a, char *type ));
int attr_delete LDAP_P(( Attribute **attrs, char *type ));
int attr_syntax LDAP_P(( char *type ));
void attr_syntax_config LDAP_P(( char *fname, int lineno, int argc, char **argv ));
AttributeType * at_find LDAP_P(( char *name ));
int at_find_in_list LDAP_P(( AttributeType *sat, AttributeType **list ));
int at_append_to_list LDAP_P(( AttributeType *sat, AttributeType ***listp ));
int at_delete_from_list LDAP_P(( int pos, AttributeType ***listp ));
int at_fake_if_needed LDAP_P(( char *name ));
/*
* ava.c
@ -230,12 +235,17 @@ void send_ldap_search_result LDAP_P(( Connection *conn, Operation *op, int err,
*/
int oc_schema_check LDAP_P(( Entry *e ));
ObjectClass *oc_find LDAP_P((char *ocname));
int oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, char **err));
/*
* schemaparse.c
*/
void parse_oc LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
void parse_oc_old LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
void parse_oc LDAP_P(( char *fname, int lineno, char * line ));
void parse_at LDAP_P(( char *fname, int lineno, char *line ));
/*
* str2filter.c
@ -311,8 +321,8 @@ extern ldap_pvt_thread_mutex_t crypt_mutex;
#endif
extern ldap_pvt_thread_mutex_t gmtime_mutex;
extern struct acl *global_acl;
extern struct objclass *global_oc;
extern struct acl *global_acl;
extern ObjectClass *global_oc;
extern int slap_init LDAP_P((int mode, char* name));
extern int slap_startup LDAP_P((int dbnum));

View File

@ -9,7 +9,6 @@
#include "slap.h"
static struct objclass *oc_find(char *ocname);
static char * oc_check_required(Entry *e, char *ocname);
static int oc_check_allowed(char *type, struct berval **ocl);
@ -64,9 +63,15 @@ oc_schema_check( Entry *e )
static char *
oc_check_required( Entry *e, char *ocname )
{
struct objclass *oc;
int i;
ObjectClass *oc;
AttributeType *at;
int i, j;
Attribute *a;
char **pp;
Debug( LDAP_DEBUG_TRACE,
"oc_check_required entry (%s), objectclass \"%s\"\n",
e->e_dn, ocname, 0 );
/* find global oc defn. it we don't know about it assume it's ok */
if ( (oc = oc_find( ocname )) == NULL ) {
@ -74,23 +79,43 @@ oc_check_required( Entry *e, char *ocname )
}
/* check for empty oc_required */
if(oc->oc_required == NULL) {
if(oc->soc_required == NULL) {
return( 0 );
}
/* for each required attribute */
for ( i = 0; oc->oc_required[i] != NULL; i++ ) {
for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
at = oc->soc_required[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 ) {
if ( at->sat_atype.at_oid &&
strcmp( a->a_type, at->sat_atype.at_oid ) == 0 ) {
break;
}
pp = at->sat_atype.at_names;
if ( pp == NULL ) {
/* Empty name list => not found */
a = NULL;
break;
}
while ( *pp ) {
if ( strcasecmp( a->a_type, *pp ) == 0 ) {
break;
}
pp++;
}
if ( *pp ) {
break;
}
}
/* not there => schema violation */
if ( a == NULL ) {
return oc->oc_required[i];
if ( at->sat_atype.at_names &&
at->sat_atype.at_names[0] ) {
return at->sat_atype.at_names[0];
} else {
return at->sat_atype.at_oid;
}
}
}
@ -114,8 +139,13 @@ oc_check_operational( char *type )
static int
oc_check_allowed( char *type, struct berval **ocl )
{
struct objclass *oc;
ObjectClass *oc;
AttributeType *at;
int i, j;
char **pp;
Debug( LDAP_DEBUG_TRACE,
"oc_check_allowed type \"%s\"\n", type, 0, 0 );
/* always allow objectclass attribute */
if ( strcasecmp( type, "objectclass" ) == 0 ) {
@ -131,22 +161,41 @@ oc_check_allowed( char *type, struct berval **ocl )
/* 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 ) {
for ( j = 0; oc->soc_required != NULL &&
oc->soc_required[j] != NULL; j++ ) {
at = oc->soc_required[j];
if ( at->sat_atype.at_oid &&
strcmp(at->sat_atype.at_oid, type ) == 0 ) {
return( 0 );
}
pp = at->sat_atype.at_names;
if ( pp == NULL )
continue;
while ( *pp ) {
if ( strcasecmp( *pp, type ) == 0 ) {
return( 0 );
}
pp++;
}
}
/* 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 )
{
for ( j = 0; oc->soc_allowed != NULL &&
oc->soc_allowed[j] != NULL; j++ ) {
at = oc->soc_allowed[j];
if ( at->sat_atype.at_oid &&
strcmp(at->sat_atype.at_oid, type ) == 0 ) {
return( 0 );
}
pp = at->sat_atype.at_names;
if ( pp == NULL )
continue;
while ( *pp ) {
if ( strcasecmp( *pp, type ) == 0 ||
strcmp( *pp, "*" ) == 0 ) {
return( 0 );
}
pp++;
}
}
/* maybe the next oc allows it */
@ -160,39 +209,271 @@ oc_check_allowed( char *type, struct berval **ocl )
return( 1 );
}
static struct objclass *
struct oindexrec {
char *oir_name;
ObjectClass *oir_oc;
};
static Avlnode *oc_index = NULL;
static AttributeType *oc_list = NULL;
static int
oc_index_cmp(
struct oindexrec *oir1,
struct oindexrec *oir2
)
{
return (strcasecmp( oir1->oir_name, oir2->oir_name ));
}
static int
oc_index_name_cmp(
char *type,
struct oindexrec *oir
)
{
return (strcasecmp( type, oir->oir_name ));
}
ObjectClass *
oc_find( char *ocname )
{
struct objclass *oc;
struct oindexrec *oir = NULL;
for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
return( oc );
if ( (oir = (struct oindexrec *) avl_find( oc_index, ocname,
(AVL_CMP) oc_index_name_cmp )) != NULL ) {
return( oir->oir_oc );
}
return( NULL );
}
static int
oc_create_required(
ObjectClass *soc,
char **attrs,
char **err
)
{
char **attrs1;
int nattrs;
AttributeType *sat;
AttributeType **satp;
int i;
if ( attrs ) {
attrs1 = attrs;
while ( *attrs1 ) {
sat = at_find(*attrs1);
if ( !sat ) {
*err = *attrs1;
return SLAP_SCHERR_ATTR_NOT_FOUND;
}
if ( at_find_in_list(sat, soc->soc_required) < 0) {
if ( at_append_to_list(sat, &soc->soc_required) ) {
*err = *attrs1;
return SLAP_SCHERR_OUTOFMEM;
}
}
attrs1++;
}
/* Now delete duplicates from the allowed list */
for ( satp = soc->soc_required; *satp; satp++ ) {
i = at_find_in_list(*satp,soc->soc_allowed);
if ( i >= 0 ) {
at_delete_from_list(i, &soc->soc_allowed);
}
}
}
return 0;
}
return( NULL );
static int
oc_create_allowed(
ObjectClass *soc,
char **attrs,
char **err
)
{
char **attrs1;
int nattrs;
AttributeType *sat;
AttributeType **satp;
int i;
if ( attrs ) {
attrs1 = attrs;
while ( *attrs1 ) {
sat = at_find(*attrs1);
if ( !sat ) {
*err = *attrs1;
return SLAP_SCHERR_ATTR_NOT_FOUND;
}
if ( at_find_in_list(sat, soc->soc_required) < 0 &&
at_find_in_list(sat, soc->soc_allowed) < 0 ) {
if ( at_append_to_list(sat, &soc->soc_allowed) ) {
*err = *attrs1;
return SLAP_SCHERR_OUTOFMEM;
}
}
attrs1++;
}
}
return 0;
}
static int
oc_add_sups(
ObjectClass *soc,
char **sups,
char **err
)
{
int code;
ObjectClass *soc1;
int nsups;
char **sups1;
int add_sups = 0;
if ( sups ) {
if ( !soc->soc_sups ) {
/* We are at the first recursive level */
add_sups = 1;
nsups = 0;
sups1 = sups;
while ( *sups1 ) {
nsups++;
sups1++;
}
nsups++;
soc->soc_sups = (ObjectClass **)ch_calloc(1,
nsups*sizeof(ObjectClass *));
}
nsups = 0;
sups1 = sups;
while ( *sups1 ) {
soc1 = oc_find(*sups1);
if ( !soc1 ) {
*err = *sups1;
return SLAP_SCHERR_CLASS_NOT_FOUND;
}
if ( add_sups )
soc->soc_sups[nsups] = soc1;
code = oc_add_sups(soc,soc1->soc_oclass.oc_sup_oids,
err);
if ( code )
return code;
if ( code = oc_create_required(soc,
soc1->soc_oclass.oc_at_oids_must,err) )
return code;
if ( code = oc_create_allowed(soc,
soc1->soc_oclass.oc_at_oids_may,err) )
return code;
nsups++;
sups1++;
}
}
return 0;
}
static int
oc_insert(
ObjectClass *soc,
char **err
)
{
ObjectClass **ocp;
struct oindexrec *oir;
char **names;
ocp = &global_oc;
while ( *ocp != NULL ) {
ocp = &(*ocp)->soc_next;
}
*ocp = soc;
if ( soc->soc_oclass.oc_oid ) {
oir = (struct oindexrec *)
ch_calloc( 1, sizeof(struct oindexrec) );
oir->oir_name = soc->soc_oclass.oc_oid;
oir->oir_oc = soc;
if ( avl_insert( &oc_index, (caddr_t) oir,
(AVL_CMP) oc_index_cmp,
(AVL_DUP) avl_dup_error ) ) {
*err = soc->soc_oclass.oc_oid;
ldap_memfree(oir);
return SLAP_SCHERR_DUP_CLASS;
}
/* FIX: temporal consistency check */
oc_find(oir->oir_name);
}
if ( (names = soc->soc_oclass.oc_names) ) {
while ( *names ) {
oir = (struct oindexrec *)
ch_calloc( 1, sizeof(struct oindexrec) );
oir->oir_name = ch_strdup(*names);
oir->oir_oc = soc;
if ( avl_insert( &oc_index, (caddr_t) oir,
(AVL_CMP) oc_index_cmp,
(AVL_DUP) avl_dup_error ) ) {
*err = *names;
ldap_memfree(oir);
return SLAP_SCHERR_DUP_CLASS;
}
/* FIX: temporal consistency check */
oc_find(oir->oir_name);
names++;
}
}
return 0;
}
int
oc_add(
LDAP_OBJECT_CLASS *oc,
char **err
)
{
ObjectClass *soc;
int code;
soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
if ( code = oc_add_sups(soc,soc->soc_oclass.oc_sup_oids,err) )
return code;
if ( code = oc_create_required(soc,soc->soc_oclass.oc_at_oids_must,err) )
return code;
if ( code = oc_create_allowed(soc,soc->soc_oclass.oc_at_oids_may,err) )
return code;
code = oc_insert(soc,err);
return code;
}
#ifdef LDAP_DEBUG
static void
oc_print( struct objclass *oc )
oc_print( ObjectClass *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] );
if ( oc->soc_oclass.oc_names && oc->soc_oclass.oc_names[0] ) {
printf( "objectclass %s\n", oc->soc_oclass.oc_names[0] );
} else {
printf( "objectclass %s\n", oc->soc_oclass.oc_oid );
}
if ( oc->soc_required != NULL ) {
printf( "\trequires %s", oc->soc_required[0] );
for ( i = 1; oc->soc_required[i] != NULL; i++ ) {
printf( ",%s", oc->soc_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] );
if ( oc->soc_allowed != NULL ) {
printf( "\tallows %s", oc->soc_allowed[0] );
for ( i = 1; oc->soc_allowed[i] != NULL; i++ ) {
printf( ",%s", oc->soc_allowed[i] );
}
printf( "\n" );
}

View File

@ -8,14 +8,38 @@
#include <ac/socket.h>
#include "slap.h"
#include "ldap_schema.h"
struct objclass *global_oc;
ObjectClass *global_oc;
static Avlnode *object_classes = NULL;
AttributeType *global_at;
int global_schemacheck = 1; /* schemacheck on is default */
static void oc_usage_old(void);
static void oc_usage(void);
static char *err2text[] = {
"",
"Out of memory",
"Objectclass not found",
"Attribute type not found",
"Duplicate objectclass",
"Duplicate attributetype"
};
char *
scherr2str(int code)
{
if ( code < 1 || code >= (sizeof(err2text)/sizeof(char *)) ) {
return "Unknown error";
} else {
return err2text[code];
}
}
void
parse_oc(
parse_oc_old(
Backend *be,
char *fname,
int lineno,
@ -25,11 +49,15 @@ parse_oc(
{
int i;
char last;
struct objclass *oc;
struct objclass **ocp;
LDAP_OBJECT_CLASS *oc;
int code;
char *err;
char **namep;
oc = (struct objclass *) ch_calloc( 1, sizeof(struct objclass) );
oc->oc_name = ch_strdup( argv[1] );
oc = (LDAP_OBJECT_CLASS *) ch_calloc( 1, sizeof(LDAP_OBJECT_CLASS) );
oc->oc_names = ch_calloc( 2, sizeof(char *) );
oc->oc_names[0] = ch_strdup( argv[1] );
oc->oc_names[1] = NULL;
for ( i = 2; i < argc; i++ ) {
/* required attributes */
if ( strcasecmp( argv[i], "requires" ) == 0 ) {
@ -38,7 +66,7 @@ parse_oc(
if ( i < argc ) {
char **s = str2charray( argv[i], "," );
last = argv[i][strlen( argv[i] ) - 1];
charray_merge( &oc->oc_required, s );
charray_merge( &oc->oc_at_oids_must, s );
charray_free( s );
}
} while ( i < argc && last == ',' );
@ -51,7 +79,7 @@ parse_oc(
char **s = str2charray( argv[i], "," );
last = argv[i][strlen( argv[i] ) - 1];
charray_merge( &oc->oc_allowed, s );
charray_merge( &oc->oc_at_oids_may, s );
charray_free( s );
}
} while ( i < argc && last == ',' );
@ -60,19 +88,95 @@ parse_oc(
fprintf( stderr,
"%s: line %d: expecting \"requires\" or \"allows\" got \"%s\"\n",
fname, lineno, argv[i] );
oc_usage();
oc_usage_old();
}
}
ocp = &global_oc;
while ( *ocp != NULL ) {
ocp = &(*ocp)->oc_next;
/*
* There was no requirement in the old schema that all attributes
* types were defined before use and they would just default to
* SYNTAX_CIS. To support this, we need to make attribute types
* out of thin air.
*/
if ( oc->oc_at_oids_must ) {
namep = oc->oc_at_oids_must;
while ( *namep ) {
code = at_fake_if_needed( *namep );
if ( code ) {
fprintf( stderr, "%s: line %d: %s %s\n",
fname, lineno, scherr2str(code), *namep);
exit( 1 );
}
namep++;
}
}
*ocp = oc;
if ( oc->oc_at_oids_may ) {
namep = oc->oc_at_oids_may;
while ( *namep ) {
code = at_fake_if_needed( *namep );
if ( code ) {
fprintf( stderr, "%s: line %d: %s %s\n",
fname, lineno, scherr2str(code), *namep);
exit( 1 );
}
namep++;
}
}
code = oc_add(oc,&err);
if ( code ) {
fprintf( stderr, "%s: line %d: %s %s\n",
fname, lineno, scherr2str(code), err);
exit( 1 );
}
ldap_memfree(oc);
}
void
parse_oc(
char *fname,
int lineno,
char *line
)
{
LDAP_OBJECT_CLASS *oc;
int code;
char *err;
oc = ldap_str2objectclass(line,&code,&err);
if ( !oc ) {
fprintf( stderr, "%s: line %d: %s before %s\n",
fname, lineno, ldap_scherr2str(code), err );
oc_usage();
}
code = oc_add(oc,&err);
if ( code ) {
fprintf( stderr, "%s: line %d: %s %s\n",
fname, lineno, scherr2str(code), err);
exit( 1 );
}
ldap_memfree(oc);
}
static void
oc_usage( void )
{
fprintf( stderr, "ObjectClassDescription = \"(\" whsp\n");
fprintf( stderr, " numericoid whsp ; ObjectClass identifier\n");
fprintf( stderr, " [ \"NAME\" qdescrs ]\n");
fprintf( stderr, " [ \"DESC\" qdstring ]\n");
fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
fprintf( stderr, " [ \"SUP\" oids ] ; Superior ObjectClasses\n");
fprintf( stderr, " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n");
fprintf( stderr, " ; default structural\n");
fprintf( stderr, " [ \"MUST\" oids ] ; AttributeTypes\n");
fprintf( stderr, " [ \"MAY\" oids ] ; AttributeTypes\n");
fprintf( stderr, "whsp \")\"\n");
exit( 1 );
}
static void
oc_usage_old( void )
{
fprintf( stderr, "<oc clause> ::= objectclass <ocname>\n" );
fprintf( stderr, " [ requires <attrlist> ]\n" );
@ -80,3 +184,54 @@ oc_usage( void )
exit( 1 );
}
static void
at_usage( void )
{
fprintf( stderr, "AttributeTypeDescription = \"(\" whsp\n");
fprintf( stderr, " numericoid whsp ; AttributeType identifier\n");
fprintf( stderr, " [ \"NAME\" qdescrs ] ; name used in AttributeType\n");
fprintf( stderr, " [ \"DESC\" qdstring ] ; description\n");
fprintf( stderr, " [ \"OBSOLETE\" whsp ]\n");
fprintf( stderr, " [ \"SUP\" woid ] ; derived from this other\n");
fprintf( stderr, " ; AttributeType\n");
fprintf( stderr, " [ \"EQUALITY\" woid ] ; Matching Rule name\n");
fprintf( stderr, " [ \"ORDERING\" woid ] ; Matching Rule name\n");
fprintf( stderr, " [ \"SUBSTR\" woid ] ; Matching Rule name\n");
fprintf( stderr, " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n");
fprintf( stderr, " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n");
fprintf( stderr, " [ \"COLLECTIVE\" whsp ] ; default not collective\n");
fprintf( stderr, " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n");
fprintf( stderr, " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n");
fprintf( stderr, " ; userApplications\n");
fprintf( stderr, " ; directoryOperation\n");
fprintf( stderr, " ; distributedOperation\n");
fprintf( stderr, " ; dSAOperation\n");
fprintf( stderr, "whsp \")\"\n");
exit( 1 );
}
void
parse_at(
char *fname,
int lineno,
char *line
)
{
LDAP_ATTRIBUTE_TYPE *at;
int code;
char *err;
at = ldap_str2attributetype(line,&code,&err);
if ( !at ) {
fprintf( stderr, "%s: line %d: %s before %s\n",
fname, lineno, ldap_scherr2str(code), err );
at_usage();
}
code = at_add(at,&err);
if ( code ) {
fprintf( stderr, "%s: line %d: %s %s\n",
fname, lineno, scherr2str(code), err);
exit( 1 );
}
ldap_memfree(at);
}

View File

@ -9,6 +9,7 @@
#include <ac/syslog.h>
#include <ac/regex.h>
#include <ac/socket.h> /* needed by LDAP_CONNECTIONLESS */
#include <ldap_schema.h>
#include "avl.h"
@ -51,6 +52,12 @@
#define SPACE(c) ((c) == ' ' || (c) == '\n')
#define NEEDSESCAPE(c) ((c) == '\\' || (c) == '"')
#define SLAP_SCHERR_OUTOFMEM 1
#define SLAP_SCHERR_CLASS_NOT_FOUND 2
#define SLAP_SCHERR_ATTR_NOT_FOUND 3
#define SLAP_SCHERR_DUP_CLASS 4
#define SLAP_SCHERR_DUP_ATTR 5
LDAP_BEGIN_DECL
extern int slap_debug;
@ -209,12 +216,32 @@ typedef struct ldapmodlist {
* represents schema information for a database
*/
struct objclass {
char *oc_name;
char **oc_required;
char **oc_allowed;
struct objclass *oc_next;
};
typedef struct slap_matching_rule {
int dummy;
} MatchingRule;
typedef struct slap_attribute_type {
LDAP_ATTRIBUTE_TYPE sat_atype;
struct slap_attribute_type *sat_sup;
struct slap_attribute_type **sat_subtypes;
MatchingRule *sat_equality;
MatchingRule *sat_ordering;
MatchingRule *sat_substr;
/*
Syntax *sat_syntax;
*/
/* The next one is created to help in the transition */
int sat_syntax_compat;
struct slap_attribute_type *sat_next;
} AttributeType;
typedef struct slap_object_class {
LDAP_OBJECT_CLASS soc_oclass;
struct slap_object_class **soc_sups;
AttributeType **soc_required;
AttributeType **soc_allowed;
struct slap_object_class *soc_next;
} ObjectClass;
/*
* Backend-info