#include "slap.h"
+#ifdef LDAP_DEBUG
+static void at_index_print( void );
+#endif
+
void
attr_free( Attribute *a )
{
#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
return( 1 );
}
+*/
+
/*
* attr_syntax - return the syntax of attribute type
*/
int
attr_syntax( char *type )
{
- struct asyntaxinfo *asi = NULL;
-
- 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 );
+ AttributeType *sat;
+
+ sat = at_find(type);
+ if ( sat ) {
+ return( sat->sat_syntax_compat );
}
return( DEFAULT_SYNTAX );
)
{
char *save;
- struct asyntaxinfo *a;
+ LDAP_ATTRIBUTE_TYPE *at;
int lasti;
+ int code;
+ char *err;
if ( argc < 2 ) {
Debug( LDAP_DEBUG_ANY,
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",
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 */
+ 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);
+}
- case 1: /* duplicate - same syntaxes */
- charray_free( a->asi_names );
- free( (char *) a );
- break;
+int
+at_fake_if_needed(
+ char *name
+)
+{
+ char *argv[3];
- default: /* inserted */
- break;
+ 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;
}
}
-#ifdef LDAP_DEBUG
+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_syntax_printnode( struct asyntaxinfo *a )
+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;
- 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] );
+ 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
+at_index_printnode( struct aindexrec *air )
+{
+
+ 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 );
}
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";
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";
#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 ) {
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
*/
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
#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));
#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);
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 ) {
}
/* 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;
+ }
}
}
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 ) {
/* 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 */
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;
+
+ 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;
+}
+
+static int
+oc_create_allowed(
+ ObjectClass *soc,
+ char **attrs,
+ char **err
+)
+{
+ char **attrs1;
+ int nattrs;
+ AttributeType *sat;
+ AttributeType **satp;
+ int i;
- for ( oc = global_oc; oc != NULL; oc = oc->oc_next ) {
- if ( strcasecmp( oc->oc_name, ocname ) == 0 ) {
- return( oc );
+ 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;
+}
- return( NULL );
+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" );
}
#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,
{
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 ) {
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 == ',' );
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 == ',' );
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++;
+ }
+ }
+ 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 );
}
- *ocp = oc;
+ 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" );
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);
+}
#include <ac/syslog.h>
#include <ac/regex.h>
#include <ac/socket.h> /* needed by LDAP_CONNECTIONLESS */
+#include <ldap_schema.h>
#include "avl.h"
#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;
* 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