From f9195f9b6f9fc995fe120a9ff0fcd01d51fd0cc8 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Sat, 5 Feb 2000 05:01:41 +0000 Subject: [PATCH] Another round of SLAPD_SCHEMA_NOT_COMPAT changes including basic structures for handing language tags and binary option (but less actual code to actually support them). Provided for reference only. Will not even compile. --- servers/slapd/Makefile.in | 6 +- servers/slapd/add.c | 7 +- servers/slapd/at.c | 563 ++++++++++++++++ servers/slapd/attr.c | 606 ++--------------- servers/slapd/back-bdb2/add.c | 2 +- servers/slapd/back-bdb2/modify.c | 2 +- servers/slapd/back-ldbm/add.c | 2 +- servers/slapd/back-ldbm/index.c | 9 + servers/slapd/back-ldbm/modify.c | 2 +- servers/slapd/backend.c | 37 +- servers/slapd/entry.c | 11 +- servers/slapd/libslapd.dsp | 20 + servers/slapd/mr.c | 206 ++++++ servers/slapd/oc.c | 456 +++++++++++++ servers/slapd/proto-slap.h | 28 +- servers/slapd/result.c | 69 +- servers/slapd/schema.c | 1036 +----------------------------- servers/slapd/schema_check.c | 271 ++++++++ servers/slapd/slap.h | 48 +- servers/slapd/syntax.c | 182 ++++++ servers/slapd/tools/Makefile.in | 3 +- servers/slapd/tools/slapadd.c | 2 +- 22 files changed, 1913 insertions(+), 1655 deletions(-) create mode 100644 servers/slapd/at.c create mode 100644 servers/slapd/mr.c create mode 100644 servers/slapd/oc.c create mode 100644 servers/slapd/schema_check.c create mode 100644 servers/slapd/syntax.c diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index bf0cca393f..b25e48efa0 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -15,7 +15,8 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \ value.c ava.c bind.c unbind.c abandon.c filterentry.c \ phonetic.c acl.c str2filter.c aclparse.c init.c user.c \ repl.c lock.c controls.c extended.c kerberos.c passwd.c \ - schema.c schema_init.c schemaparse.c \ + schema.c schema_check.c schema_init.c schemaparse.c \ + at.c mr.c syntax.c oc.c \ monitor.c configinfo.c starttls.c \ root_dse.c sasl.c module.c suffixalias.c $(@PLAT@_SRCS) @@ -25,7 +26,8 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \ value.o ava.o bind.o unbind.o abandon.o filterentry.o \ phonetic.o acl.o str2filter.o aclparse.o init.o user.o \ repl.o lock.o controls.o extended.o kerberos.o passwd.o \ - schema.o schema_init.o schemaparse.o \ + schema.o schema_check.o schema_init.o schemaparse.o \ + at.o mr.o syntax.o oc.o \ monitor.o configinfo.o starttls.o \ root_dse.o sasl.o module.o suffixalias.o $(@PLAT@_OBJS) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 8fef1b17b3..11069badee 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -244,7 +244,12 @@ add_created_attrs( Operation *op, Entry *e ) /* return error on any attempts by the user to add these attrs */ for ( a = e->e_attrs; a != NULL; a = a->a_next ) { - if ( oc_check_op_no_usermod_attr( a->a_type ) ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + if ( is_at_no_user_mod( a->a_desc.ad_type )) +#else + if ( oc_check_op_no_usermod_attr( a->a_type ) ) +#endif + { return LDAP_CONSTRAINT_VIOLATION; } } diff --git a/servers/slapd/at.c b/servers/slapd/at.c new file mode 100644 index 0000000000..2538e143ee --- /dev/null +++ b/servers/slapd/at.c @@ -0,0 +1,563 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* at.c - routines for dealing with attributes */ + +#include "portable.h" + +#include + +#include +#include +#include +#include +#include + +#include "ldap_pvt.h" +#include "slap.h" + +#ifndef SLAPD_SCHEMA_NOT_COMPAT +char * +at_canonical_name( const char * a_type ) +{ + AttributeType *atp; + + atp=at_find(a_type); + + if ( atp == NULL ) { + return (char *) a_type; + + } else if ( atp->sat_names + && atp->sat_names[0] && (*(atp->sat_names[0]) != '\0') ) + { + return atp->sat_names[0]; + + } else if (atp->sat_oid && (*atp->sat_oid != '\0')) { + return atp->sat_oid; + } + + return (char *) a_type; +} + +#define DEFAULT_SYNTAX SYNTAX_CIS + +/* + * attr_syntax - return the syntax of attribute type + */ + +int +attr_syntax( const char *type ) +{ + AttributeType *sat; + + sat = at_find(type); + if ( sat ) { + return( sat->sat_syntax_compat ); + } + + return( DEFAULT_SYNTAX ); +} + +/* + * attr_syntax_config - process an attribute syntax config line + */ + +void +attr_syntax_config( + const char *fname, + int lineno, + int argc, + char **argv +) +{ + char *save; + LDAP_ATTRIBUTE_TYPE *at; + int lasti; + int code; + const char *err; + + if ( argc < 2 ) { + Debug( LDAP_DEBUG_ANY, +"%s: line %d: missing name in \"attribute + \" (ignored)\n", + fname, lineno, 0 ); + return; + } + + at = (LDAP_ATTRIBUTE_TYPE *) + ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) ); + +#define SYNTAX_DS_OID "1.3.6.1.4.1.1466.115.121.1.15" +#define SYNTAX_DSCE_OID "2.5.13.5" +#define SYNTAX_IA5_OID "1.3.6.1.4.1.1466.115.121.1.26" +#define SYNTAX_IA5CE_OID "1.3.6.1.4.1.1466.109.114.1" +#define SYNTAX_DN_OID SLAPD_OID_DN_SYNTAX +#define SYNTAX_TEL_OID "1.3.6.1.4.1.1466.115.121.1.50" +#define SYNTAX_BIN_OID "1.3.6.1.4.1.1466.115.121.1.40" /* octetString */ + + lasti = argc - 1; + if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 || + strcasecmp( argv[lasti], "cis" ) == 0 ) { + at->at_syntax_oid = SYNTAX_DS_OID; + at->at_equality_oid = "2.5.13.2"; + at->at_ordering_oid = "2.5.13.3"; + at->at_substr_oid = "2.5.13.4"; + + } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 || + strcasecmp( argv[lasti], "tel" ) == 0 ) { + at->at_syntax_oid = SYNTAX_TEL_OID; + at->at_equality_oid = "2.5.13.20"; + at->at_substr_oid = "2.5.13.21"; + + } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) { + at->at_syntax_oid = SYNTAX_DN_OID; + at->at_equality_oid = "2.5.13.1"; + + } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 || + strcasecmp( argv[lasti], "ces" ) == 0 ) { + at->at_syntax_oid = SYNTAX_DS_OID; + at->at_equality_oid = SYNTAX_DSCE_OID; + at->at_ordering_oid = "2.5.13.6"; + at->at_substr_oid = "2.5.13.7"; + + } else if ( strcasecmp( argv[lasti], "binary" ) == 0 || + strcasecmp( argv[lasti], "bin" ) == 0 ) { + /* bin -> octetString, not binary! */ + at->at_syntax_oid = SYNTAX_BIN_OID; + at->at_equality_oid = "2.5.13.17"; + + } else { + Debug( LDAP_DEBUG_ANY, + "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n", + fname, lineno, argv[lasti] ); + Debug( LDAP_DEBUG_ANY, + "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n", + 0, 0, 0 ); + free( (AttributeType *) at ); + return; + } + + save = argv[lasti]; + argv[lasti] = NULL; + at->at_names = charray_dup( argv ); + argv[lasti] = save; + + code = at_add( at, &err ); + if ( code ) { + fprintf( stderr, "%s: line %d: %s %s\n", + fname, lineno, scherr2str(code), err); + exit( EXIT_FAILURE ); + } + + ldap_memfree(at); +} + +int +at_fake_if_needed( + const char *name +) +{ + char *argv[3]; + + if ( at_find( name ) ) { + return 0; + } else { + argv[0] = (char*) name; + argv[1] = "cis"; + argv[2] = NULL; + attr_syntax_config( "implicit", 0, 2, argv ); + return 0; + } +} + +#endif + + + +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( + const char *name +) +{ + struct aindexrec *air; + char *tmpname; + +#ifndef SLAPD_SCHEMA_NOT_COMPAT + /* + * The name may actually be an AttributeDescription, i.e. it may + * contain options. + */ + /* Treat any attribute type with option as an unknown attribute type */ + char *p = strchr( name, ';' ); + if ( p ) { + tmpname = ch_malloc( p-name+1 ); + strncpy( tmpname, name, p-name ); + tmpname[p-name] = '\0'; + } else +#endif + { + tmpname = (char *)name; + } + + if ( (air = (struct aindexrec *) avl_find( attr_index, tmpname, + (AVL_CMP) attr_index_name_cmp )) != NULL ) { + if ( tmpname != name ) + ldap_memfree( tmpname ); + return( air->air_at ); + } + + if ( tmpname != name ) + ldap_memfree( tmpname ); + 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, + const char **err +) +{ + AttributeType **atp; + struct aindexrec *air; + char **names; + + atp = &attr_list; + while ( *atp != NULL ) { + atp = &(*atp)->sat_next; + } + *atp = sat; + + if ( sat->sat_oid ) { + air = (struct aindexrec *) + ch_calloc( 1, sizeof(struct aindexrec) ); + air->air_name = sat->sat_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_oid; + ldap_memfree(air); + return SLAP_SCHERR_DUP_ATTR; + } + /* FIX: temporal consistency check */ + at_find(air->air_name); + } + + if ( (names = sat->sat_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->air_name); + 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, + const char **err +) +{ + AttributeType *sat; + MatchingRule *mr; + Syntax *syn; + int code; + char *cname; + + if ( at->at_names && at->at_names[0] ) { + cname = at->at_names[0]; + } else if ( at->at_oid ) { + cname = at->at_oid; + } else { + cname = ""; + return SLAP_SCHERR_ATTR_INCOMPLETE; + } + sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) ); + memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE)); + +#ifdef SLAPD_SCHEMA_NOT_COMPAT + sat->sat_cname = cname; +#endif + + if ( at->at_sup_oid ) { + AttributeType *supsat = at_find(at->at_sup_oid); + + if ( (supsat == NULL ) ) { + *err = at->at_sup_oid; + return SLAP_SCHERR_ATTR_NOT_FOUND; + } + + sat->sat_sup = supsat; + + if ( at_append_to_list(sat, &supsat->sat_subtypes) ) { + *err = cname; + return SLAP_SCHERR_OUTOFMEM; + } + } + + /* + * Inherit definitions from superiors. We only check the + * direct superior since that one has already inherited from + * its own superiorss + */ + if ( sat->sat_sup ) { + sat->sat_syntax = sat->sat_sup->sat_syntax; + + sat->sat_equality = sat->sat_sup->sat_equality; + sat->sat_ordering = sat->sat_sup->sat_ordering; + sat->sat_substr = sat->sat_sup->sat_substr; + } + + if ( at->at_syntax_oid ) { + if ( (syn = syn_find(sat->sat_syntax_oid)) ) { + sat->sat_syntax = syn; + } else { + *err = sat->sat_syntax_oid; + return SLAP_SCHERR_SYN_NOT_FOUND; + } + +#ifndef SLAPD_SCHEMA_NOT_COMPAT + if ( !strcmp(at->at_syntax_oid, SYNTAX_DS_OID) ) { + if ( at->at_equality_oid && ( + !strcmp(at->at_equality_oid, SYNTAX_DSCE_OID) ) ) + { + sat->sat_syntax_compat = SYNTAX_CES; + } else { + sat->sat_syntax_compat = SYNTAX_CIS; + } + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_IA5_OID) ) { + if ( at->at_equality_oid && ( + !strcmp(at->at_equality_oid, SYNTAX_IA5CE_OID) ) ) + { + sat->sat_syntax_compat = SYNTAX_CES; + } else { + sat->sat_syntax_compat = SYNTAX_CIS; + } + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_DN_OID ) ) { + sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN; + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_TEL_OID ) ) { + sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL; + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_BIN_OID ) ) { + sat->sat_syntax_compat = SYNTAX_BIN; + + } else { + sat->sat_syntax_compat = DEFAULT_SYNTAX; + } +#endif + + } else if ( sat->sat_syntax == NULL ) { + return SLAP_SCHERR_ATTR_INCOMPLETE; + } + + if ( sat->sat_equality_oid ) { + if ( (mr = mr_find(sat->sat_equality_oid)) ) { + sat->sat_equality = mr; + } else { + *err = sat->sat_equality_oid; + return SLAP_SCHERR_MR_NOT_FOUND; + } + + } + + if ( sat->sat_ordering_oid ) { + if ( (mr = mr_find(sat->sat_ordering_oid)) ) { + sat->sat_ordering = mr; + } else { + *err = sat->sat_ordering_oid; + return SLAP_SCHERR_MR_NOT_FOUND; + } + } + + if ( sat->sat_substr_oid ) { + if ( (mr = mr_find(sat->sat_substr_oid)) ) { + sat->sat_substr = mr; + } else { + *err = sat->sat_substr_oid; + return SLAP_SCHERR_MR_NOT_FOUND; + } + } + + 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 +at_index_print( void ) +{ + printf("Printing attribute type index:\n"); + (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode, + 0, -1, AVL_INORDER ); +} +#endif + +#if defined( SLAPD_SCHEMA_DN ) +int +at_schema_info( Entry *e ) +{ + struct berval val; + struct berval *vals[2]; + AttributeType *at; + + vals[0] = &val; + vals[1] = NULL; + + for ( at = attr_list; at; at = at->sat_next ) { + val.bv_val = ldap_attributetype2str( &at->sat_atype ); + if ( val.bv_val ) { + val.bv_len = strlen( val.bv_val ); + Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n", + (long) val.bv_len, val.bv_val, 0 ); + attr_merge( e, "attributeTypes", vals ); + ldap_memfree( val.bv_val ); + } else { + return -1; + } + } + return 0; +} +#endif diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c index 0d95e2887f..0621645f03 100644 --- a/servers/slapd/attr.c +++ b/servers/slapd/attr.c @@ -26,10 +26,28 @@ static void at_index_print( void ); #endif +#ifdef SLAPD_SCHEMA_NOT_COMPAT +void +ad_free( AttributeDescription *ad, int freeit ) +{ + if( ad == NULL ) return; + + ber_bvfree( ad->ad_cname ); + free( ad->ad_lang ); + + if( freeit ) free( ad ); +} +#endif + void attr_free( Attribute *a ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ + ad_free( &a->a_desc, 0 ); +#else free( a->a_type ); +#endif ber_bvecfree( a->a_vals ); free( a ); } @@ -74,8 +92,13 @@ Attribute *attr_dup( Attribute *a ) tmp->a_vals = NULL; } +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ + tmp->a_desc = a->a_desc; + tmp->a_desc.ad_cname = ber_bvdup( a->a_desc.ad_cname ); + tmp->a_desc.ad_lang = ch_strdup( a->a_desc.ad_lang ); +#else tmp->a_type = ch_strdup( a->a_type ); -#ifndef SLAPD_SCHEMA_NOT_COMPAT tmp->a_syntax = a->a_syntax; #endif tmp->a_next = NULL; @@ -101,6 +124,7 @@ Attribute *attrs_dup( Attribute *a ) return tmp; } +#ifndef SLAPD_SCHEMA_NOT_COMPAT /* * attr_normalize - normalize an attribute name (make it all lowercase) */ @@ -112,7 +136,9 @@ attr_normalize( char *s ) return( ldap_pvt_str2lower( s ) ); } +#endif +#ifndef SLAPD_SCHEMA_NOT_COMPAT /* * attr_merge_fast - merge the given type and value with the list of * attributes in attrs. called from str2entry(), where we can make some @@ -134,17 +160,21 @@ attr_merge_fast( { if ( *a == NULL ) { for ( *a = &e->e_attrs; **a != NULL; *a = &(**a)->a_next ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else if ( strcasecmp( (**a)->a_type, type ) == 0 ) { break; } +#endif } } if ( **a == NULL ) { **a = (Attribute *) ch_malloc( sizeof(Attribute) ); - (**a)->a_type = attr_normalize( ch_strdup( type ) ); (**a)->a_vals = NULL; #ifndef SLAPD_SCHEMA_NOT_COMPAT + (**a)->a_type = attr_normalize( ch_strdup( type ) ); (**a)->a_syntax = attr_syntax( type ); #endif (**a)->a_next = NULL; @@ -153,6 +183,7 @@ attr_merge_fast( return( value_add_fast( &(**a)->a_vals, vals, nvals, naddvals, maxvals ) ); } +#endif /* * attr_merge - merge the given type and value with the list of @@ -171,18 +202,24 @@ attr_merge( Attribute **a; for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else if ( strcasecmp( (*a)->a_type, type ) == 0 ) { break; } +#endif } if ( *a == NULL ) { *a = (Attribute *) ch_malloc( sizeof(Attribute) ); +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else (*a)->a_type = attr_normalize( ch_strdup( type ) ); - (*a)->a_vals = NULL; -#ifndef SLAPD_SCHEMA_NOT_COMPAT (*a)->a_syntax = attr_syntax( type ); #endif + (*a)->a_vals = NULL; (*a)->a_next = NULL; } @@ -190,19 +227,23 @@ attr_merge( } /* - * attr_find - find and return attribute type in list a + * attr_find - find attribute by type */ Attribute * attr_find( Attribute *a, - const char *type + const char *type ) { for ( ; a != NULL; a = a->a_next ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else if ( strcasecmp( a->a_type, type ) == 0 ) { return( a ); } +#endif } return( NULL ); @@ -225,9 +266,13 @@ attr_delete( Attribute *save; for ( a = attrs; *a != NULL; a = &(*a)->a_next ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else if ( strcasecmp( (*a)->a_type, type ) == 0 ) { break; } +#endif } if ( *a == NULL ) { @@ -241,552 +286,3 @@ attr_delete( return( 0 ); } -#ifndef SLAPD_SCHEMA_NOT_COMPAT - -#define DEFAULT_SYNTAX SYNTAX_CIS - -/* - * attr_syntax - return the syntax of attribute type - */ - -int -attr_syntax( const char *type ) -{ - AttributeType *sat; - - sat = at_find(type); - if ( sat ) { - return( sat->sat_syntax_compat ); - } - - return( DEFAULT_SYNTAX ); -} - -/* - * attr_syntax_config - process an attribute syntax config line - */ - -void -attr_syntax_config( - const char *fname, - int lineno, - int argc, - char **argv -) -{ - char *save; - LDAP_ATTRIBUTE_TYPE *at; - int lasti; - int code; - const char *err; - - if ( argc < 2 ) { - Debug( LDAP_DEBUG_ANY, -"%s: line %d: missing name in \"attribute + \" (ignored)\n", - fname, lineno, 0 ); - return; - } - - at = (LDAP_ATTRIBUTE_TYPE *) - ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) ); - -#define SYNTAX_DS_OID "1.3.6.1.4.1.1466.115.121.1.15" -#define SYNTAX_DSCE_OID "2.5.13.5" -#define SYNTAX_IA5_OID "1.3.6.1.4.1.1466.115.121.1.26" -#define SYNTAX_IA5CE_OID "1.3.6.1.4.1.1466.109.114.1" -#define SYNTAX_DN_OID SLAPD_OID_DN_SYNTAX -#define SYNTAX_TEL_OID "1.3.6.1.4.1.1466.115.121.1.50" -#define SYNTAX_BIN_OID "1.3.6.1.4.1.1466.115.121.1.40" /* octetString */ - - lasti = argc - 1; - if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 || - strcasecmp( argv[lasti], "cis" ) == 0 ) { - at->at_syntax_oid = SYNTAX_DS_OID; - at->at_equality_oid = "2.5.13.2"; - at->at_ordering_oid = "2.5.13.3"; - at->at_substr_oid = "2.5.13.4"; - - } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 || - strcasecmp( argv[lasti], "tel" ) == 0 ) { - at->at_syntax_oid = SYNTAX_TEL_OID; - at->at_equality_oid = "2.5.13.20"; - at->at_substr_oid = "2.5.13.21"; - - } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) { - at->at_syntax_oid = SYNTAX_DN_OID; - at->at_equality_oid = "2.5.13.1"; - - } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 || - strcasecmp( argv[lasti], "ces" ) == 0 ) { - at->at_syntax_oid = SYNTAX_DS_OID; - at->at_equality_oid = SYNTAX_DSCE_OID; - at->at_ordering_oid = "2.5.13.6"; - at->at_substr_oid = "2.5.13.7"; - - } else if ( strcasecmp( argv[lasti], "binary" ) == 0 || - strcasecmp( argv[lasti], "bin" ) == 0 ) { - /* bin -> octetString, not binary! */ - at->at_syntax_oid = SYNTAX_BIN_OID; - at->at_equality_oid = "2.5.13.17"; - - } else { - Debug( LDAP_DEBUG_ANY, - "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n", - fname, lineno, argv[lasti] ); - Debug( LDAP_DEBUG_ANY, - "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n", - 0, 0, 0 ); - free( (AttributeType *) at ); - return; - } - - save = argv[lasti]; - argv[lasti] = NULL; - at->at_names = charray_dup( argv ); - argv[lasti] = save; - - code = at_add( at, &err ); - if ( code ) { - fprintf( stderr, "%s: line %d: %s %s\n", - fname, lineno, scherr2str(code), err); - exit( EXIT_FAILURE ); - } - - ldap_memfree(at); -} - -int -at_fake_if_needed( - const char *name -) -{ - char *argv[3]; - - if ( at_find( name ) ) { - return 0; - } else { - argv[0] = (char*) name; - argv[1] = "cis"; - argv[2] = NULL; - attr_syntax_config( "implicit", 0, 2, argv ); - return 0; - } -} -#endif - -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( - const char *name -) -{ - struct aindexrec *air; - char *tmpname; - -#ifndef SLAPD_SCHEMA_NOT_COMPAT - /* - * The name may actually be an AttributeDescription, i.e. it may - * contain options. - */ - /* Treat any attribute type with option as an unknown attribute type */ - char *p = strchr( name, ';' ); - if ( p ) { - tmpname = ch_malloc( p-name+1 ); - strncpy( tmpname, name, p-name ); - tmpname[p-name] = '\0'; - } else -#endif - { - tmpname = (char *)name; - } - - if ( (air = (struct aindexrec *) avl_find( attr_index, tmpname, - (AVL_CMP) attr_index_name_cmp )) != NULL ) { - if ( tmpname != name ) - ldap_memfree( tmpname ); - return( air->air_at ); - } - - if ( tmpname != name ) - ldap_memfree( tmpname ); - 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, - const char **err -) -{ - AttributeType **atp; - struct aindexrec *air; - char **names; - - atp = &attr_list; - while ( *atp != NULL ) { - atp = &(*atp)->sat_next; - } - *atp = sat; - - if ( sat->sat_oid ) { - air = (struct aindexrec *) - ch_calloc( 1, sizeof(struct aindexrec) ); - air->air_name = sat->sat_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_oid; - ldap_memfree(air); - return SLAP_SCHERR_DUP_ATTR; - } - /* FIX: temporal consistency check */ - at_find(air->air_name); - } - if ( (names = sat->sat_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->air_name); - 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, - const char **err -) -{ - AttributeType *sat; - AttributeType *sat1; - MatchingRule *mr; - Syntax *syn; - int code; - char *errattr; - - if ( at->at_names && at->at_names[0] ) { - errattr = at->at_names[0]; - } else if ( at->at_oid ) { - errattr = at->at_oid; - } else { - errattr = ""; - return SLAP_SCHERR_ATTR_INCOMPLETE; - } - 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 = at->at_sup_oid; - return SLAP_SCHERR_ATTR_NOT_FOUND; - } - } - - /* - * Inherit definitions from superiors. We only check the - * direct superior since that one has already inherited from - * its own superiorss - */ - if ( sat->sat_sup ) { - sat->sat_syntax = sat->sat_sup->sat_syntax; - - sat->sat_equality = sat->sat_sup->sat_equality; - sat->sat_ordering = sat->sat_sup->sat_ordering; - sat->sat_substr = sat->sat_sup->sat_substr; - } - - if ( at->at_syntax_oid ) { - if ( (syn = syn_find(sat->sat_syntax_oid)) ) { - sat->sat_syntax = syn; - } else { - *err = sat->sat_syntax_oid; - return SLAP_SCHERR_SYN_NOT_FOUND; - } - -#ifndef SLAPD_SCHEMA_NOT_COMPAT - if ( !strcmp(at->at_syntax_oid, SYNTAX_DS_OID) ) { - if ( at->at_equality_oid && ( - !strcmp(at->at_equality_oid, SYNTAX_DSCE_OID) ) ) - { - sat->sat_syntax_compat = SYNTAX_CES; - } else { - sat->sat_syntax_compat = SYNTAX_CIS; - } - - } else if ( !strcmp(at->at_syntax_oid, SYNTAX_IA5_OID) ) { - if ( at->at_equality_oid && ( - !strcmp(at->at_equality_oid, SYNTAX_IA5CE_OID) ) ) - { - sat->sat_syntax_compat = SYNTAX_CES; - } else { - sat->sat_syntax_compat = SYNTAX_CIS; - } - - } else if ( !strcmp(at->at_syntax_oid, SYNTAX_DN_OID ) ) { - sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN; - - } else if ( !strcmp(at->at_syntax_oid, SYNTAX_TEL_OID ) ) { - sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL; - - } else if ( !strcmp(at->at_syntax_oid, SYNTAX_BIN_OID ) ) { - sat->sat_syntax_compat = SYNTAX_BIN; - - } else { - sat->sat_syntax_compat = DEFAULT_SYNTAX; - } -#endif - - } else if ( sat->sat_syntax == NULL ) { - return SLAP_SCHERR_ATTR_INCOMPLETE; - } - - if ( sat->sat_equality_oid ) { - if ( (mr = mr_find(sat->sat_equality_oid)) ) { - sat->sat_equality = mr; - } else { - *err = sat->sat_equality_oid; - return SLAP_SCHERR_MR_NOT_FOUND; - } - - } - - if ( sat->sat_ordering_oid ) { - if ( (mr = mr_find(sat->sat_ordering_oid)) ) { - sat->sat_ordering = mr; - } else { - *err = sat->sat_ordering_oid; - return SLAP_SCHERR_MR_NOT_FOUND; - } - } - - if ( sat->sat_substr_oid ) { - if ( (mr = mr_find(sat->sat_substr_oid)) ) { - sat->sat_substr = mr; - } else { - *err = sat->sat_substr_oid; - return SLAP_SCHERR_MR_NOT_FOUND; - } - } - - code = at_insert(sat,err); - return code; -} - - -char * -#ifdef SLAPD_SCHEMA_NOT_COMPAT -at_canonical_name( AttributeType * atp ) -#else -at_canonical_name( const char * a_type ) -#endif -{ -#ifndef SLAPD_SCHEMA_NOT_COMPAT - AttributeType *atp; - - atp=at_find(a_type); -#endif - - if ( atp == NULL ) { -#ifdef SLAPD_SCHEMA_NOT_COMPAT - return NULL; -#else - return (char *) a_type; -#endif - - } else if ( atp->sat_names - && atp->sat_names[0] && (*(atp->sat_names[0]) != '\0') ) - { - return atp->sat_names[0]; - - } else if (atp->sat_oid && (*atp->sat_oid != '\0')) { - return atp->sat_oid; - } - -#ifdef SLAPD_SCHEMA_NOT_COMPAT - return NULL; -#else - return (char *) a_type; -#endif -} - -#if defined( SLAPD_SCHEMA_DN ) -int -at_schema_info( Entry *e ) -{ - struct berval val; - struct berval *vals[2]; - AttributeType *at; - - vals[0] = &val; - vals[1] = NULL; - - for ( at = attr_list; at; at = at->sat_next ) { - val.bv_val = ldap_attributetype2str( &at->sat_atype ); - if ( val.bv_val ) { - val.bv_len = strlen( val.bv_val ); - Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n", - (long) val.bv_len, val.bv_val, 0 ); - attr_merge( e, "attributeTypes", vals ); - ldap_memfree( val.bv_val ); - } else { - return -1; - } - } - return 0; -} -#endif - -#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 -at_index_print( void ) -{ - printf("Printing attribute type index:\n"); - (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode, - 0, -1, AVL_INORDER ); -} -#endif diff --git a/servers/slapd/back-bdb2/add.c b/servers/slapd/back-bdb2/add.c index b72dc51512..2ab81e76a6 100644 --- a/servers/slapd/back-bdb2/add.c +++ b/servers/slapd/back-bdb2/add.c @@ -38,7 +38,7 @@ bdb2i_back_add_internal( return( -1 ); } - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + if ( schema_check_entry( e ) != 0 ) { Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0, 0 ); diff --git a/servers/slapd/back-bdb2/modify.c b/servers/slapd/back-bdb2/modify.c index badab589eb..bcb6f1c394 100644 --- a/servers/slapd/back-bdb2/modify.c +++ b/servers/slapd/back-bdb2/modify.c @@ -74,7 +74,7 @@ bdb2i_back_modify_internal( } /* check that the entry still obeys the schema */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + if ( schema_check_entry( e ) != 0 ) { Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL, NULL, NULL ); diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index edeaf57a10..fce939ddd2 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -43,7 +43,7 @@ ldbm_back_add( return( -1 ); } - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + if ( schema_check_entry( e ) != 0 ) { ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", diff --git a/servers/slapd/back-ldbm/index.c b/servers/slapd/back-ldbm/index.c index 1e746fc8f9..6c90a6f179 100644 --- a/servers/slapd/back-ldbm/index.c +++ b/servers/slapd/back-ldbm/index.c @@ -15,6 +15,7 @@ #include "slap.h" #include "back-ldbm.h" + static int change_value(Backend *be, DBCache *db, char *type, @@ -51,7 +52,11 @@ index_add_entry( /* add the dn to the indexes */ { char *dn = ch_strdup("dn"); +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else index_change_values( be, dn, bvals, e->e_id, SLAP_INDEX_ADD_OP ); +#endif free( dn ); } @@ -59,8 +64,12 @@ index_add_entry( /* add each attribute to the indexes */ for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* index_change_values( be, SLAP_INDEX_ADD_OP, e->e_id, ap ); */ +#else index_change_values( be, ap->a_type, ap->a_vals, e->e_id, SLAP_INDEX_ADD_OP ); +#endif } Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id, diff --git a/servers/slapd/back-ldbm/modify.c b/servers/slapd/back-ldbm/modify.c index d22fcc614c..f30a153a42 100644 --- a/servers/slapd/back-ldbm/modify.c +++ b/servers/slapd/back-ldbm/modify.c @@ -95,7 +95,7 @@ int ldbm_modify_internal( ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex ); /* check that the entry still obeys the schema */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + if ( schema_check_entry( e ) != 0 ) { attrs_free( e->e_attrs ); e->e_attrs = save_attrs; Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 ); diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index c2ed169b9a..8dd65ff26e 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -633,26 +633,27 @@ backend_group( } #ifdef SLAPD_SCHEMA_DN -Attribute *backend_subschemasubentry( Backend *be ) +Attribute *backend_operational( + Backend *be, + Entry *e ) { - /* - * This routine returns points to STATIC data!!! - */ - /* and should be backend specific */ - - static struct berval ss_val = { - sizeof(SLAPD_SCHEMA_DN)-1, - SLAPD_SCHEMA_DN }; - static struct berval *ss_vals[2] = { &ss_val, NULL }; - static Attribute ss_attr = { - "subschemasubentry", - ss_vals, -#ifndef SLAPD_SCHEMA_NOT_COMPAT - SYNTAX_DN | SYNTAX_CIS, + Attribute *a = ch_malloc( sizeof( Attribute ) ); +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else + a->a_type = "subschemasubentry"; + a->a_syntax = SYNTAX_DN | SYNTAX_CIS; #endif - NULL - }; - return &ss_attr; + /* Should be backend specific */ + a->a_vals = ch_malloc( 2 * sizeof( struct berval * ) ); + a->a_vals[0] = ch_malloc( sizeof( struct berval ) ); + a->a_vals[0]->bv_val = strdup( SLAPD_SCHEMA_DN ); + a->a_vals[0]->bv_len = sizeof( SLAPD_SCHEMA_DN ) - 1; + a->a_vals[1] = NULL; + + a->a_next = NULL; + + return a; } #endif diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index b0cd52e28f..86abbae9c1 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -197,9 +197,18 @@ entry2str( /* put ":[:] " line for each value */ for ( i = 0; a->a_vals[i] != NULL; i++ ) { bv = a->a_vals[i]; +#ifdef SLAPD_SCHEMA_NOT_COMPAT + tmplen = a->a_desc.ad_cname->bv_len; +#else tmplen = strlen( a->a_type ); +#endif MAKE_SPACE( LDIF_SIZE_NEEDED( tmplen, bv->bv_len )); - ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, a->a_type, + ldif_sput( (char **) &ecur, LDIF_PUT_VALUE, +#ifdef SLAPD_SCHEMA_NOT_COMPAT + a->a_desc.ad_cname->bv_val, +#else + a->a_type, +#endif bv->bv_val, bv->bv_len ); } } diff --git a/servers/slapd/libslapd.dsp b/servers/slapd/libslapd.dsp index 8e2d0200ca..fa3e332047 100644 --- a/servers/slapd/libslapd.dsp +++ b/servers/slapd/libslapd.dsp @@ -140,6 +140,10 @@ SOURCE=.\add.c # End Source File # Begin Source File +SOURCE=.\at.c +# End Source File +# Begin Source File + SOURCE=.\attr.c # End Source File # Begin Source File @@ -236,6 +240,14 @@ SOURCE=.\monitor.c # End Source File # Begin Source File +SOURCE=.\mr.c +# End Source File +# Begin Source File + +SOURCE=.\oc.c +# End Source File +# Begin Source File + SOURCE=.\operation.c # End Source File # Begin Source File @@ -268,6 +280,10 @@ SOURCE=.\schema.c # End Source File # Begin Source File +SOURCE=.\schema_check.c +# End Source File +# Begin Source File + SOURCE=.\schema_init.c # End Source File # Begin Source File @@ -292,6 +308,10 @@ SOURCE=.\suffixalias.c # End Source File # Begin Source File +SOURCE=.\syntax.c +# End Source File +# Begin Source File + SOURCE=.\unbind.c # End Source File # Begin Source File diff --git a/servers/slapd/mr.c b/servers/slapd/mr.c new file mode 100644 index 0000000000..8dbfb96c78 --- /dev/null +++ b/servers/slapd/mr.c @@ -0,0 +1,206 @@ +/* mr.c - routines to manage matching rule definitions */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include +#include + +#include "slap.h" +#include "ldap_pvt.h" + + +struct mindexrec { + char *mir_name; + MatchingRule *mir_mr; +}; + +static Avlnode *mr_index = NULL; +static MatchingRule *mr_list = NULL; + +static int +mr_index_cmp( + struct mindexrec *mir1, + struct mindexrec *mir2 +) +{ + return (strcmp( mir1->mir_name, mir2->mir_name )); +} + +static int +mr_index_name_cmp( + char *name, + struct mindexrec *mir +) +{ + return (strcmp( name, mir->mir_name )); +} + +MatchingRule * +mr_find( const char *mrname ) +{ + struct mindexrec *mir = NULL; + + if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname, + (AVL_CMP) mr_index_name_cmp )) != NULL ) { + return( mir->mir_mr ); + } + return( NULL ); +} + +static int +mr_insert( + MatchingRule *smr, + const char **err +) +{ + MatchingRule **mrp; + struct mindexrec *mir; + char **names; + + mrp = &mr_list; + while ( *mrp != NULL ) { + mrp = &(*mrp)->smr_next; + } + *mrp = smr; + + if ( smr->smr_oid ) { + mir = (struct mindexrec *) + ch_calloc( 1, sizeof(struct mindexrec) ); + mir->mir_name = smr->smr_oid; + mir->mir_mr = smr; + if ( avl_insert( &mr_index, (caddr_t) mir, + (AVL_CMP) mr_index_cmp, + (AVL_DUP) avl_dup_error ) ) { + *err = smr->smr_oid; + ldap_memfree(mir); + return SLAP_SCHERR_DUP_RULE; + } + /* FIX: temporal consistency check */ + mr_find(mir->mir_name); + } + if ( (names = smr->smr_names) ) { + while ( *names ) { + mir = (struct mindexrec *) + ch_calloc( 1, sizeof(struct mindexrec) ); + mir->mir_name = ch_strdup(*names); + mir->mir_mr = smr; + if ( avl_insert( &mr_index, (caddr_t) mir, + (AVL_CMP) mr_index_cmp, + (AVL_DUP) avl_dup_error ) ) { + *err = *names; + ldap_memfree(mir); + return SLAP_SCHERR_DUP_RULE; + } + /* FIX: temporal consistency check */ + mr_find(mir->mir_name); + names++; + } + } + return 0; +} + +int +mr_add( + LDAP_MATCHING_RULE *mr, + slap_mr_convert_func *convert, + slap_mr_normalize_func *normalize, + slap_mr_match_func *match, + slap_mr_indexer_func *indexer, + slap_mr_filter_func *filter, + const char **err +) +{ + MatchingRule *smr; + Syntax *syn; + int code; + + smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) ); + memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE)); + + smr->smr_convert = convert; + smr->smr_normalize = normalize; + smr->smr_match = match; + smr->smr_indexer = indexer; + smr->smr_filter = filter; + + if ( smr->smr_syntax_oid ) { + if ( (syn = syn_find(smr->smr_syntax_oid)) ) { + smr->smr_syntax = syn; + } else { + *err = smr->smr_syntax_oid; + return SLAP_SCHERR_SYN_NOT_FOUND; + } + } else { + *err = ""; + return SLAP_SCHERR_MR_INCOMPLETE; + } + code = mr_insert(smr,err); + return code; +} + + +int +register_matching_rule( + char * desc, + slap_mr_convert_func *convert, + slap_mr_normalize_func *normalize, + slap_mr_match_func *match, + slap_mr_indexer_func *indexer, + slap_mr_filter_func *filter ) +{ + LDAP_MATCHING_RULE *mr; + int code; + const char *err; + + mr = ldap_str2matchingrule( desc, &code, &err); + if ( !mr ) { + Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n", + ldap_scherr2str(code), err, desc ); + return( -1 ); + } + + code = mr_add( mr, convert, normalize, match, indexer, filter, &err ); + if ( code ) { + Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n", + scherr2str(code), err, desc ); + return( -1 ); + } + return( 0 ); +} + + +#if defined( SLAPD_SCHEMA_DN ) + +int mr_schema_info( Entry *e ) +{ + struct berval val; + struct berval *vals[2]; + MatchingRule *mr; + + vals[0] = &val; + vals[1] = NULL; + + for ( mr = mr_list; mr; mr = mr->smr_next ) { + val.bv_val = ldap_matchingrule2str( &mr->smr_mrule ); + if ( val.bv_val ) { + val.bv_len = strlen( val.bv_val ); + Debug( LDAP_DEBUG_TRACE, "Merging mr [%ld] %s\n", + (long) val.bv_len, val.bv_val, 0 ); + attr_merge( e, "matchingRules", vals ); + ldap_memfree( val.bv_val ); + } else { + return -1; + } + } + return 0; +} + +#endif diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c new file mode 100644 index 0000000000..88e180983f --- /dev/null +++ b/servers/slapd/oc.c @@ -0,0 +1,456 @@ +/* oc.c - object class routines */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include +#include + +#include "slap.h" +#include "ldap_pvt.h" + +int is_entry_objectclass( + Entry* e, + const char* oc) +{ + Attribute *attr; + struct berval bv; + + if( e == NULL || oc == NULL || *oc == '\0' ) + return 0; + + /* + * find objectClass attribute + */ + attr = attr_find(e->e_attrs, "objectclass"); + + if( attr == NULL ) { + /* no objectClass attribute */ + return 0; + } + + bv.bv_val = (char *) oc; + bv.bv_len = strlen( bv.bv_val ); + +#ifdef SLAPD_SCHEMA_NOT_COMPAT + /* not yet implemented */ +#else + if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { + /* entry is not of this objectclass */ + return 0; + } +#endif + + return 1; +} + + +#ifndef SLAPD_SCHEMA_NOT_COMPAT + /* these shouldn't be hardcoded */ + +static char *oc_op_usermod_attrs[] = { + /* + * these are operational attributes which are + * not defined as NO-USER_MODIFICATION and + * which slapd supports modification of. + * + * Currently none. + * Likely candidate, "aci" + */ + NULL +}; + +static char *oc_op_attrs[] = { + /* + * these are operational attributes + * most could be user modifiable + */ + "objectClasses", + "attributeTypes", + "matchingRules", + "matchingRuleUse", + "dITStructureRules", + "dITContentRules", + "nameForms", + "ldapSyntaxes", + "namingContexts", + "supportedExtension", + "supportedControl", + "supportedSASLMechanisms", + "supportedLDAPversion", + "supportedACIMechanisms", + "subschemaSubentry", /* NO USER MOD */ + NULL + +}; + +/* this list should be extensible */ +static char *oc_op_no_usermod_attrs[] = { + /* + * Operational and 'no user modification' attributes + * which are STORED in the directory server. + */ + + /* RFC2252, 3.2.1 */ + "creatorsName", + "createTimestamp", + "modifiersName", + "modifyTimestamp", + + NULL +}; +#endif + + +/* + * check to see if attribute is 'operational' or not. + */ +int +oc_check_op_attr( const char *type ) +{ +#ifndef SLAPD_SCHEMA_NOT_COMPAT + return charray_inlist( oc_op_attrs, type ) + || charray_inlist( oc_op_usermod_attrs, type ) + || charray_inlist( oc_op_no_usermod_attrs, type ); +#else + AttributeType *at = at_find( type ); + + if( at == NULL ) return 0; + + return at->sat_usage != LDAP_SCHEMA_USER_APPLICATIONS; +#endif +} + +/* + * check to see if attribute can be user modified or not. + */ +int +oc_check_op_usermod_attr( const char *type ) +{ +#ifndef SLAPD_SCHEMA_NOT_COMPAT + return charray_inlist( oc_op_usermod_attrs, type ); +#else + /* not (yet) in schema */ + return 0; +#endif +} + +/* + * check to see if attribute is 'no user modification' or not. + */ +int +oc_check_op_no_usermod_attr( const char *type ) +{ +#ifndef SLAPD_SCHEMA_NOT_COMPAT + return charray_inlist( oc_op_no_usermod_attrs, type ); +#else + AttributeType *at = at_find( type ); + + if( at == NULL ) return 0; + + return at->sat_no_user_mod; +#endif +} + + +struct oindexrec { + char *oir_name; + ObjectClass *oir_oc; +}; + +static Avlnode *oc_index = NULL; +static ObjectClass *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 *name, + struct oindexrec *oir +) +{ + return (strcasecmp( name, oir->oir_name )); +} + +ObjectClass * +oc_find( const char *ocname ) +{ + 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, + const char **err +) +{ + char **attrs1; + 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, + const char **err +) +{ + 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 ( 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, + const 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_sup_oids, err); + if ( code ) + return code; + + code = oc_create_required(soc,soc1->soc_at_oids_must,err); + if ( code ) + return code; + code = oc_create_allowed(soc,soc1->soc_at_oids_may,err); + if ( code ) + return code; + + nsups++; + sups1++; + } + } + return 0; +} + +static int +oc_insert( + ObjectClass *soc, + const char **err +) +{ + ObjectClass **ocp; + struct oindexrec *oir; + char **names; + + ocp = &oc_list; + while ( *ocp != NULL ) { + ocp = &(*ocp)->soc_next; + } + *ocp = soc; + + if ( soc->soc_oid ) { + oir = (struct oindexrec *) + ch_calloc( 1, sizeof(struct oindexrec) ); + oir->oir_name = soc->soc_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_oid; + ldap_memfree(oir); + return SLAP_SCHERR_DUP_CLASS; + } + /* FIX: temporal consistency check */ + oc_find(oir->oir_name); + } + if ( (names = soc->soc_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, + const 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_sup_oids,err)) != 0 ) + return code; + if ( (code = oc_create_required(soc,soc->soc_at_oids_must,err)) != 0 ) + return code; + if ( (code = oc_create_allowed(soc,soc->soc_at_oids_may,err)) != 0 ) + return code; + code = oc_insert(soc,err); + 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 + + +#if defined( SLAPD_SCHEMA_DN ) + +int +oc_schema_info( Entry *e ) +{ + struct berval val; + struct berval *vals[2]; + ObjectClass *oc; + + vals[0] = &val; + vals[1] = NULL; + + for ( oc = oc_list; oc; oc = oc->soc_next ) { + val.bv_val = ldap_objectclass2str( &oc->soc_oclass ); + if ( val.bv_val ) { + val.bv_len = strlen( val.bv_val ); + Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n", + (long) val.bv_len, val.bv_val, 0 ); + attr_merge( e, "objectClasses", vals ); + ldap_memfree( val.bv_val ); + } else { + return -1; + } + } + return 0; +} + +#endif diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 83d03eba59..0fdac434cb 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -70,14 +70,15 @@ LIBSLAPD_F (int) at_fake_if_needed LDAP_P(( const char *name )); LIBSLAPD_F (int) at_schema_info LDAP_P(( Entry *e )); LIBSLAPD_F (int) at_add LDAP_P(( LDAP_ATTRIBUTE_TYPE *at, const char **err )); +LIBSLAPD_F (void) attrs_free LDAP_P(( Attribute *a )); +LIBSLAPD_F (Attribute *) attrs_dup LDAP_P(( Attribute *a )); + #ifdef SLAPD_SCHEMA_NOT_COMPAT -LIBSLAPD_F (char *) at_canonical_name LDAP_P(( AttributeType *a_type )); +# define at_canonical_name(at) ((at)->sat_cname) #else LIBSLAPD_F (char *) at_canonical_name LDAP_P(( const char * a_type )); #endif -LIBSLAPD_F (void) attrs_free LDAP_P(( Attribute *a )); -LIBSLAPD_F (Attribute *) attrs_dup LDAP_P(( Attribute *a )); /* * ava.c @@ -138,10 +139,8 @@ LIBSLAPD_F (int) backend_group LDAP_P((Backend *be, )); #endif -#ifdef SLAPD_SCHEMA_DN -/* temporary extern for temporary routine*/ -LIBSLAPD_F (Attribute *) backend_subschemasubentry( Backend * ); -#endif +LIBSLAPD_F (Attribute *) backend_operational( Backend *, Entry * ); + /* @@ -455,11 +454,19 @@ LIBSLAPD_F (int) sasl_bind LDAP_P((Backend *, char *, char *, char *, struct berval *, char **)); #endif +/* oc.c */ +LIBSLAPD_F (int) oc_schema_info( Entry *e ); + +/* mr.c */ +LIBSLAPD_F (int) mr_schema_info( Entry *e ); + +/* syntax.c */ +LIBSLAPD_F (int) syn_schema_info( Entry *e ); + /* * schema.c */ -LIBSLAPD_F (int) oc_schema_check LDAP_P(( Entry *e )); LIBSLAPD_F (int) oc_check_op_attr LDAP_P(( const char *type )); LIBSLAPD_F (int) oc_check_op_usermod_attr LDAP_P(( const char *type )); LIBSLAPD_F (int) oc_check_op_no_usermod_attr LDAP_P(( const char *type )); @@ -503,6 +510,11 @@ LIBSLAPD_F (int) is_entry_objectclass LDAP_P(( #define is_entry_alias(e) is_entry_objectclass((e), "ALIAS") #define is_entry_referral(e) is_entry_objectclass((e), "REFERRAL") +/* + * schema_check.c + */ +LIBSLAPD_F (int) schema_check_entry LDAP_P(( Entry *e )); + /* * schema_init.c diff --git a/servers/slapd/result.c b/servers/slapd/result.c index ab5b12750e..f90c92e930 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -612,7 +612,7 @@ send_search_entry( ) { BerElement *ber; - Attribute *a; + Attribute *a, *aa; int i, rc=-1, bytes; char *edn; int userattrs; @@ -659,36 +659,40 @@ send_search_entry( : charray_inlist( attrs, LDAP_ALL_OPERATIONAL_ATTRIBUTES ); for ( a = e->e_attrs; a != NULL; a = a->a_next ) { + char *desc; +#ifdef SLAPD_SCHEMA_NOT_COMPAT + desc = a->a_desc.ad_type->sat_cname; +#else + desc = a->a_type; +#endif + if ( attrs == NULL ) { /* all addrs request, skip operational attributes */ - if( !opattrs && oc_check_op_attr( a->a_type ) ) { + if( !opattrs && oc_check_op_attr( desc ) ) { continue; } } else { /* specific addrs requested */ - if ( oc_check_op_attr( a->a_type ) ) { - if( !opattrs && !charray_inlist( attrs, a->a_type ) ) - { + if ( oc_check_op_attr( desc ) ) + { + if( !opattrs && !charray_inlist( attrs, desc ) ) { continue; } } else { - if (!userattrs && !charray_inlist( attrs, a->a_type ) ) - { + if (!userattrs && !charray_inlist( attrs, desc ) ) { continue; } } } - if ( ! access_allowed( be, conn, op, e, - a->a_type, NULL, ACL_READ ) ) - { + if ( ! access_allowed( be, conn, op, e, desc, NULL, ACL_READ ) ) { Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s not allowed\n", - a->a_type, 0, 0 ); + desc, 0, 0 ); continue; } - if (( rc = ber_printf( ber, "{s[" /*]}*/ , a->a_type )) == -1 ) { + if (( rc = ber_printf( ber, "{s[" /*]}*/ , desc )) == -1 ) { Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, @@ -699,11 +703,11 @@ send_search_entry( if ( ! attrsonly ) { for ( i = 0; a->a_vals[i] != NULL; i++ ) { if ( ! access_allowed( be, conn, op, e, - a->a_type, a->a_vals[i], ACL_READ ) ) + desc, a->a_vals[i], ACL_READ ) ) { Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s, value %d not allowed\n", - a->a_type, i, 0 ); + desc, i, 0 ); continue; } @@ -727,42 +731,46 @@ send_search_entry( } } -#ifdef SLAPD_SCHEMA_DN /* eventually will loop through generated operational attributes */ /* only have subschemaSubentry implemented */ - a = backend_subschemasubentry( be ); + aa = backend_operational( be, e ); - do { + for (a = aa ; a == NULL; a = a->a_next ) { + char *desc; +#ifdef SLAPD_SCHEMA_NOT_COMPAT + desc = a->a_desc.ad_type->sat_cname; +#else + desc = a->a_type; +#endif + if ( attrs == NULL ) { /* all addrs request, skip operational attributes */ - if( !opattrs && oc_check_op_attr( a->a_type ) ) { + if( !opattrs && oc_check_op_attr( desc ) ) { continue; } } else { /* specific addrs requested */ - if ( oc_check_op_attr( a->a_type ) ) { - if( !opattrs && !charray_inlist( attrs, a->a_type ) ) + if ( oc_check_op_attr( desc ) ) { + if( !opattrs && !charray_inlist( attrs, desc ) ) { continue; } } else { - if (!userattrs && !charray_inlist( attrs, a->a_type ) ) + if (!userattrs && !charray_inlist( attrs, desc ) ) { continue; } } } - if ( ! access_allowed( be, conn, op, e, - a->a_type, NULL, ACL_READ ) ) - { + if ( ! access_allowed( be, conn, op, e, desc, NULL, ACL_READ ) ) { Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s not allowed\n", - a->a_type, 0, 0 ); + desc, 0, 0 ); continue; } - if (( rc = ber_printf( ber, "{s[" /*]}*/ , a->a_type )) == -1 ) { + if (( rc = ber_printf( ber, "{s[" /*]}*/ , desc )) == -1 ) { Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); ber_free( ber, 1 ); send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, @@ -773,11 +781,11 @@ send_search_entry( if ( ! attrsonly ) { for ( i = 0; a->a_vals[i] != NULL; i++ ) { if ( ! access_allowed( be, conn, op, e, - a->a_type, a->a_vals[i], ACL_READ ) ) + desc, a->a_vals[i], ACL_READ ) ) { Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s, value %d not allowed\n", - a->a_type, i, 0 ); + desc, i, 0 ); continue; } @@ -800,8 +808,9 @@ send_search_entry( NULL, "encode end error", NULL, NULL ); goto error_return; } - } while (0); -#endif + } + + attrs_free( aa ); rc = ber_printf( ber, /*{{{*/ "}}}" ); diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c index ab847d391f..3318ee1aa9 100644 --- a/servers/slapd/schema.c +++ b/servers/slapd/schema.c @@ -1,4 +1,4 @@ -/* schema.c - routines to enforce schema definitions */ +/* schema.c - routines to manage schema definitions */ /* $OpenLDAP$ */ /* * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. @@ -16,959 +16,9 @@ #include "slap.h" #include "ldap_pvt.h" -static char * oc_check_required(Entry *e, char *ocname); -static int oc_check_allowed(char *type, struct berval **ocl); - -/* - * oc_check - check that entry e conforms to the schema required by - * its object class(es). returns 0 if so, non-zero otherwise. - */ - -int -oc_schema_check( Entry *e ) -{ - Attribute *a, *aoc; - ObjectClass *oc; - int i; - int ret = 0; - - - /* find the object class attribute - could error out here */ - if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) { - Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n", - e->e_dn, 0, 0 ); - return( 1 ); - } - - /* check that the entry has required attrs for each oc */ - for ( i = 0; aoc->a_vals[i] != NULL; i++ ) { - if ( (oc = oc_find( aoc->a_vals[i]->bv_val )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "Objectclass \"%s\" not defined\n", - aoc->a_vals[i]->bv_val, 0, 0 ); - } - else - { - char *s = oc_check_required( e, aoc->a_vals[i]->bv_val ); - - if (s != NULL) { - Debug( LDAP_DEBUG_ANY, - "Entry (%s), oc \"%s\" requires attr \"%s\"\n", - e->e_dn, aoc->a_vals[i]->bv_val, s ); - ret = 1; - } - } - } - - if ( ret != 0 ) { - return( ret ); - } - - /* check that each attr in the entry is allowed by some oc */ - for ( a = e->e_attrs; a != NULL; a = a->a_next ) { - if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) { - Debug( LDAP_DEBUG_ANY, - "Entry (%s), attr \"%s\" not allowed\n", - e->e_dn, a->a_type, 0 ); - ret = 1; - } - } - - return( ret ); -} - -static char * -oc_check_required( Entry *e, char *ocname ) -{ - ObjectClass *oc; - AttributeType *at; - int i; - 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 ) { - return( 0 ); - } - - /* check for empty oc_required */ - if(oc->soc_required == NULL) { - return( 0 ); - } - - /* for each required attribute */ - 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 ( at->sat_oid && - strcmp( a->a_type, at->sat_oid ) == 0 ) { - break; - } - pp = at->sat_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 ) { - if ( at->sat_names && at->sat_names[0] ) { - return at->sat_names[0]; - } else { - return at->sat_oid; - } - } - } - - return( NULL ); -} - -static int -oc_check_allowed( char *type, struct berval **ocl ) -{ - ObjectClass *oc; - AttributeType *at; - int i, j; - char **pp; - char *p, *t; - - Debug( LDAP_DEBUG_TRACE, - "oc_check_allowed type \"%s\"\n", type, 0, 0 ); - - /* always allow objectclass attribute */ - if ( strcasecmp( type, "objectclass" ) == 0 ) { - return( 0 ); - } - -#ifndef SLAPD_SCHEMA_NOT_COMPAT - /* Treat any attribute type with option as an unknown attribute type */ - /* - * The "type" we have received is actually an AttributeDescription. - * Let's find out the corresponding type. - */ - p = strchr( type, ';' ); - if ( p ) { - t = ch_malloc( p-type+1 ); - strncpy( t, type, p-type ); - t[p-type] = '\0'; - Debug( LDAP_DEBUG_TRACE, - "oc_check_allowed type \"%s\" from \"%s\"\n", - t, type, 0 ); - - } else -#endif - { - t = type; - } - - - /* - * All operational attributions are allowed by schema rules. - */ - if ( oc_check_op_attr( t ) ) { - return( 0 ); - } - - /* check that the type appears as req or opt in at least one oc */ - for ( i = 0; ocl[i] != NULL; i++ ) { - /* if we know about the oc */ - if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) { - /* does it require the type? */ - for ( j = 0; oc->soc_required != NULL && - oc->soc_required[j] != NULL; j++ ) { - at = oc->soc_required[j]; - if ( at->sat_oid && - strcmp(at->sat_oid, t ) == 0 ) { - if ( t != type ) - ldap_memfree( t ); - return( 0 ); - } - pp = at->sat_names; - if ( pp == NULL ) - continue; - while ( *pp ) { - if ( strcasecmp( *pp, t ) == 0 ) { - if ( t != type ) - ldap_memfree( t ); - return( 0 ); - } - pp++; - } - } - /* does it allow the type? */ - for ( j = 0; oc->soc_allowed != NULL && - oc->soc_allowed[j] != NULL; j++ ) { - at = oc->soc_allowed[j]; - if ( at->sat_oid && - strcmp( at->sat_oid, t ) == 0 ) { - if ( t != type ) - ldap_memfree( t ); - return( 0 ); - } - pp = at->sat_names; - if ( pp == NULL ) - continue; - while ( *pp ) { - if ( strcasecmp( *pp, t ) == 0 || - strcmp( *pp, "*" ) == 0 ) { - if ( t != type ) - ldap_memfree( t ); - return( 0 ); - } - pp++; - } - } - /* maybe the next oc allows it */ - -#ifdef OC_UNDEFINED_IMPLES_EXTENSIBLE - /* we don't know about the oc. assume it allows it */ - } else { - if ( t != type ) - ldap_memfree( t ); - return( 0 ); -#endif - } - } - - if ( t != type ) - ldap_memfree( t ); - /* not allowed by any oc */ - return( 1 ); -} - - -#ifndef SLAPD_SCHEMA_NOT_COMPAT - /* these shouldn't be hardcoded */ - -static char *oc_op_usermod_attrs[] = { - /* - * these are operational attributes which are - * not defined as NO-USER_MODIFICATION and - * which slapd supports modification of. - * - * Currently none. - * Likely candidate, "aci" - */ - NULL -}; - -static char *oc_op_attrs[] = { - /* - * these are operational attributes - * most could be user modifiable - */ - "objectClasses", - "attributeTypes", - "matchingRules", - "matchingRuleUse", - "dITStructureRules", - "dITContentRules", - "nameForms", - "ldapSyntaxes", - "namingContexts", - "supportedExtension", - "supportedControl", - "supportedSASLMechanisms", - "supportedLDAPversion", - "supportedACIMechanisms", - "subschemaSubentry", /* NO USER MOD */ - NULL - -}; - -/* this list should be extensible */ -static char *oc_op_no_usermod_attrs[] = { - /* - * Operational and 'no user modification' attributes - * which are STORED in the directory server. - */ - - /* RFC2252, 3.2.1 */ - "creatorsName", - "createTimestamp", - "modifiersName", - "modifyTimestamp", - - NULL -}; -#endif - - -/* - * check to see if attribute is 'operational' or not. - */ -int -oc_check_op_attr( const char *type ) -{ -#ifndef SLAPD_SCHEMA_NOT_COMPAT - return charray_inlist( oc_op_attrs, type ) - || charray_inlist( oc_op_usermod_attrs, type ) - || charray_inlist( oc_op_no_usermod_attrs, type ); -#else - AttributeType *at = at_find( type ); - - if( at == NULL ) return 0; - - return at->sat_usage != LDAP_SCHEMA_USER_APPLICATIONS; -#endif -} - -/* - * check to see if attribute can be user modified or not. - */ -int -oc_check_op_usermod_attr( const char *type ) -{ -#ifndef SLAPD_SCHEMA_NOT_COMPAT - return charray_inlist( oc_op_usermod_attrs, type ); -#else - /* not (yet) in schema */ - return 0; -#endif -} - -/* - * check to see if attribute is 'no user modification' or not. - */ -int -oc_check_op_no_usermod_attr( const char *type ) -{ -#ifndef SLAPD_SCHEMA_NOT_COMPAT - return charray_inlist( oc_op_no_usermod_attrs, type ); -#else - AttributeType *at = at_find( type ); - - if( at == NULL ) return 0; - - return at->sat_no_user_mod; -#endif -} - - -struct oindexrec { - char *oir_name; - ObjectClass *oir_oc; -}; - -static Avlnode *oc_index = NULL; -static ObjectClass *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 *name, - struct oindexrec *oir -) -{ - return (strcasecmp( name, oir->oir_name )); -} - -ObjectClass * -oc_find( const char *ocname ) -{ - 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, - const char **err -) -{ - char **attrs1; - 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, - const char **err -) -{ - 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 ( 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, - const 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_sup_oids, err); - if ( code ) - return code; - - code = oc_create_required(soc,soc1->soc_at_oids_must,err); - if ( code ) - return code; - code = oc_create_allowed(soc,soc1->soc_at_oids_may,err); - if ( code ) - return code; - - nsups++; - sups1++; - } - } - return 0; -} - -static int -oc_insert( - ObjectClass *soc, - const char **err -) -{ - ObjectClass **ocp; - struct oindexrec *oir; - char **names; - - ocp = &oc_list; - while ( *ocp != NULL ) { - ocp = &(*ocp)->soc_next; - } - *ocp = soc; - - if ( soc->soc_oid ) { - oir = (struct oindexrec *) - ch_calloc( 1, sizeof(struct oindexrec) ); - oir->oir_name = soc->soc_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_oid; - ldap_memfree(oir); - return SLAP_SCHERR_DUP_CLASS; - } - /* FIX: temporal consistency check */ - oc_find(oir->oir_name); - } - if ( (names = soc->soc_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, - const 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_sup_oids,err)) != 0 ) - return code; - if ( (code = oc_create_required(soc,soc->soc_at_oids_must,err)) != 0 ) - return code; - if ( (code = oc_create_allowed(soc,soc->soc_at_oids_may,err)) != 0 ) - return code; - code = oc_insert(soc,err); - return code; -} - -struct sindexrec { - char *sir_name; - Syntax *sir_syn; -}; - -static Avlnode *syn_index = NULL; -static Syntax *syn_list = NULL; - -static int -syn_index_cmp( - struct sindexrec *sir1, - struct sindexrec *sir2 -) -{ - return (strcmp( sir1->sir_name, sir2->sir_name )); -} - -static int -syn_index_name_cmp( - char *name, - struct sindexrec *sir -) -{ - return (strcmp( name, sir->sir_name )); -} - -Syntax * -syn_find( const char *synname ) -{ - struct sindexrec *sir = NULL; - - if ( (sir = (struct sindexrec *) avl_find( syn_index, synname, - (AVL_CMP) syn_index_name_cmp )) != NULL ) { - return( sir->sir_syn ); - } - return( NULL ); -} - -Syntax * -syn_find_desc( const char *syndesc, int *len ) -{ - Syntax *synp; - - for (synp = syn_list; synp; synp = synp->ssyn_next) - if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{'))) - return synp; - return( NULL ); -} - -static int -syn_insert( - Syntax *ssyn, - const char **err -) -{ - Syntax **synp; - struct sindexrec *sir; - - synp = &syn_list; - while ( *synp != NULL ) { - synp = &(*synp)->ssyn_next; - } - *synp = ssyn; - - if ( ssyn->ssyn_oid ) { - sir = (struct sindexrec *) - ch_calloc( 1, sizeof(struct sindexrec) ); - sir->sir_name = ssyn->ssyn_oid; - sir->sir_syn = ssyn; - if ( avl_insert( &syn_index, (caddr_t) sir, - (AVL_CMP) syn_index_cmp, - (AVL_DUP) avl_dup_error ) ) { - *err = ssyn->ssyn_oid; - ldap_memfree(sir); - return SLAP_SCHERR_DUP_SYNTAX; - } - /* FIX: temporal consistency check */ - syn_find(sir->sir_name); - } - return 0; -} - -int -syn_add( - LDAP_SYNTAX *syn, - int flags, - slap_syntax_validate_func *validate, - slap_syntax_transform_func *ber2str, - slap_syntax_transform_func *str2ber, - const char **err -) -{ - Syntax *ssyn; - int code; - - ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) ); - memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX)); - - ssyn->ssyn_flags = flags; - ssyn->ssyn_validate = validate; - ssyn->ssyn_ber2str = ber2str; - ssyn->ssyn_str2ber = str2ber; - - code = syn_insert(ssyn,err); - return code; -} - -struct mindexrec { - char *mir_name; - MatchingRule *mir_mr; -}; - -static Avlnode *mr_index = NULL; -static MatchingRule *mr_list = NULL; - -static int -mr_index_cmp( - struct mindexrec *mir1, - struct mindexrec *mir2 -) -{ - return (strcmp( mir1->mir_name, mir2->mir_name )); -} - -static int -mr_index_name_cmp( - char *name, - struct mindexrec *mir -) -{ - return (strcmp( name, mir->mir_name )); -} - -MatchingRule * -mr_find( const char *mrname ) -{ - struct mindexrec *mir = NULL; - - if ( (mir = (struct mindexrec *) avl_find( mr_index, mrname, - (AVL_CMP) mr_index_name_cmp )) != NULL ) { - return( mir->mir_mr ); - } - return( NULL ); -} - -static int -mr_insert( - MatchingRule *smr, - const char **err -) -{ - MatchingRule **mrp; - struct mindexrec *mir; - char **names; - - mrp = &mr_list; - while ( *mrp != NULL ) { - mrp = &(*mrp)->smr_next; - } - *mrp = smr; - - if ( smr->smr_oid ) { - mir = (struct mindexrec *) - ch_calloc( 1, sizeof(struct mindexrec) ); - mir->mir_name = smr->smr_oid; - mir->mir_mr = smr; - if ( avl_insert( &mr_index, (caddr_t) mir, - (AVL_CMP) mr_index_cmp, - (AVL_DUP) avl_dup_error ) ) { - *err = smr->smr_oid; - ldap_memfree(mir); - return SLAP_SCHERR_DUP_RULE; - } - /* FIX: temporal consistency check */ - mr_find(mir->mir_name); - } - if ( (names = smr->smr_names) ) { - while ( *names ) { - mir = (struct mindexrec *) - ch_calloc( 1, sizeof(struct mindexrec) ); - mir->mir_name = ch_strdup(*names); - mir->mir_mr = smr; - if ( avl_insert( &mr_index, (caddr_t) mir, - (AVL_CMP) mr_index_cmp, - (AVL_DUP) avl_dup_error ) ) { - *err = *names; - ldap_memfree(mir); - return SLAP_SCHERR_DUP_RULE; - } - /* FIX: temporal consistency check */ - mr_find(mir->mir_name); - names++; - } - } - return 0; -} - -int -mr_add( - LDAP_MATCHING_RULE *mr, - slap_mr_convert_func *convert, - slap_mr_normalize_func *normalize, - slap_mr_match_func *match, - slap_mr_indexer_func *indexer, - slap_mr_filter_func *filter, - const char **err -) -{ - MatchingRule *smr; - Syntax *syn; - int code; - - smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) ); - memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE)); - - smr->smr_convert = convert; - smr->smr_normalize = normalize; - smr->smr_match = match; - smr->smr_indexer = indexer; - smr->smr_filter = filter; - - if ( smr->smr_syntax_oid ) { - if ( (syn = syn_find(smr->smr_syntax_oid)) ) { - smr->smr_syntax = syn; - } else { - *err = smr->smr_syntax_oid; - return SLAP_SCHERR_SYN_NOT_FOUND; - } - } else { - *err = ""; - return SLAP_SCHERR_MR_INCOMPLETE; - } - code = mr_insert(smr,err); - return code; -} - -int -register_syntax( - char * desc, int flags, - slap_syntax_validate_func *validate, - slap_syntax_transform_func *ber2str, - slap_syntax_transform_func *str2ber ) -{ - LDAP_SYNTAX *syn; - int code; - const char *err; - - syn = ldap_str2syntax( desc, &code, &err); - if ( !syn ) { - Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n", - ldap_scherr2str(code), err, desc ); - return( -1 ); - } - - code = syn_add( syn, flags, validate, ber2str, str2ber, &err ); - if ( code ) { - Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n", - scherr2str(code), err, desc ); - return( -1 ); - } - - return( 0 ); -} - -int -register_matching_rule( - char * desc, - slap_mr_convert_func *convert, - slap_mr_normalize_func *normalize, - slap_mr_match_func *match, - slap_mr_indexer_func *indexer, - slap_mr_filter_func *filter ) -{ - LDAP_MATCHING_RULE *mr; - int code; - const char *err; - - mr = ldap_str2matchingrule( desc, &code, &err); - if ( !mr ) { - Debug( LDAP_DEBUG_ANY, "Error in register_matching_rule: %s before %s in %s\n", - ldap_scherr2str(code), err, desc ); - return( -1 ); - } - - code = mr_add( mr, convert, normalize, match, indexer, filter, &err ); - if ( code ) { - Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n", - scherr2str(code), err, desc ); - return( -1 ); - } - return( 0 ); -} - #if defined( SLAPD_SCHEMA_DN ) -static int -syn_schema_info( Entry *e ) -{ - struct berval val; - struct berval *vals[2]; - Syntax *syn; - - vals[0] = &val; - vals[1] = NULL; - - for ( syn = syn_list; syn; syn = syn->ssyn_next ) { - val.bv_val = ldap_syntax2str( &syn->ssyn_syn ); - if ( val.bv_val ) { - val.bv_len = strlen( val.bv_val ); - Debug( LDAP_DEBUG_TRACE, "Merging syn [%ld] %s\n", - (long) val.bv_len, val.bv_val, 0 ); - attr_merge( e, "ldapSyntaxes", vals ); - ldap_memfree( val.bv_val ); - } else { - return -1; - } - } - return 0; -} - -static int -mr_schema_info( Entry *e ) -{ - struct berval val; - struct berval *vals[2]; - MatchingRule *mr; - - vals[0] = &val; - vals[1] = NULL; - - for ( mr = mr_list; mr; mr = mr->smr_next ) { - val.bv_val = ldap_matchingrule2str( &mr->smr_mrule ); - if ( val.bv_val ) { - val.bv_len = strlen( val.bv_val ); - Debug( LDAP_DEBUG_TRACE, "Merging mr [%ld] %s\n", - (long) val.bv_len, val.bv_val, 0 ); - attr_merge( e, "matchingRules", vals ); - ldap_memfree( val.bv_val ); - } else { - return -1; - } - } - return 0; -} - -static int -oc_schema_info( Entry *e ) -{ - struct berval val; - struct berval *vals[2]; - ObjectClass *oc; - - vals[0] = &val; - vals[1] = NULL; - - for ( oc = oc_list; oc; oc = oc->soc_next ) { - val.bv_val = ldap_objectclass2str( &oc->soc_oclass ); - if ( val.bv_val ) { - val.bv_len = strlen( val.bv_val ); - Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n", - (long) val.bv_len, val.bv_val, 0 ); - attr_merge( e, "objectClasses", vals ); - ldap_memfree( val.bv_val ); - } else { - return -1; - } - } - return 0; -} - void schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) { @@ -1001,24 +51,15 @@ schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) free( rdn ); } - if ( syn_schema_info( e ) ) { - /* Out of memory, do something about it */ - entry_free( e ); - return; - } - if ( mr_schema_info( e ) ) { - /* Out of memory, do something about it */ - entry_free( e ); - return; - } - if ( at_schema_info( e ) ) { - /* Out of memory, do something about it */ - entry_free( e ); - return; - } - if ( oc_schema_info( e ) ) { + if ( syn_schema_info( e ) + || mr_schema_info( e ) + || at_schema_info( e ) + || oc_schema_info( e ) ) + { /* Out of memory, do something about it */ entry_free( e ); + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, + NULL, NULL, NULL, NULL ); return; } @@ -1047,64 +88,3 @@ schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly ) } #endif -#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 is_entry_objectclass( - Entry* e, - const char* oc) -{ - Attribute *attr; - struct berval bv; - - if( e == NULL || oc == NULL || *oc == '\0' ) - return 0; - - /* - * find objectClass attribute - */ - attr = attr_find(e->e_attrs, "objectclass"); - - if( attr == NULL ) { - /* no objectClass attribute */ - return 0; - } - - bv.bv_val = (char *) oc; - bv.bv_len = strlen( bv.bv_val ); - -#ifdef SLAPD_SCHEMA_NOT_COMPAT - /* not yet implemented */ -#else - if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) { - /* entry is not of this objectclass */ - return 0; - } -#endif - - return 1; -} diff --git a/servers/slapd/schema_check.c b/servers/slapd/schema_check.c new file mode 100644 index 0000000000..25bbd5486a --- /dev/null +++ b/servers/slapd/schema_check.c @@ -0,0 +1,271 @@ +/* schema_check.c - routines to enforce schema definitions */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include +#include + +#include "slap.h" +#include "ldap_pvt.h" + +static char * oc_check_required(Entry *e, char *ocname); +static int oc_check_allowed(char *type, struct berval **ocl); + +/* + * entry_schema_check - check that entry e conforms to the schema required + * by its object class(es). + * + * returns 0 if so, non-zero otherwise. + */ + +int +schema_check_entry( Entry *e ) +{ + Attribute *a, *aoc; + ObjectClass *oc; + int i; + int ret = 0; + + if( !global_schemacheck ) return 0; + + /* find the object class attribute - could error out here */ + if ( (aoc = attr_find( e->e_attrs, "objectclass" )) == NULL ) { + Debug( LDAP_DEBUG_ANY, "No object class for entry (%s)\n", + e->e_dn, 0, 0 ); + return( 1 ); + } + + /* check that the entry has required attrs for each oc */ + for ( i = 0; aoc->a_vals[i] != NULL; i++ ) { + if ( (oc = oc_find( aoc->a_vals[i]->bv_val )) == NULL ) { + Debug( LDAP_DEBUG_ANY, + "Objectclass \"%s\" not defined\n", + aoc->a_vals[i]->bv_val, 0, 0 ); + } + else + { + char *s = oc_check_required( e, aoc->a_vals[i]->bv_val ); + + if (s != NULL) { + Debug( LDAP_DEBUG_ANY, + "Entry (%s), oc \"%s\" requires attr \"%s\"\n", + e->e_dn, aoc->a_vals[i]->bv_val, s ); + ret = 1; + } + } + } + + if ( ret != 0 ) { + return( ret ); + } + + /* check that each attr in the entry is allowed by some oc */ + for ( a = e->e_attrs; a != NULL; a = a->a_next ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + if ( oc_check_allowed( a->a_desc.ad_type, aoc->a_vals ) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "Entry (%s), attr \"%s\" not allowed\n", + e->e_dn, a->a_desc.ad_cname->bv_val, 0 ); + ret = 1; + } +#else + if ( oc_check_allowed( a->a_type, aoc->a_vals ) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "Entry (%s), attr \"%s\" not allowed\n", + e->e_dn, a->a_type, 0 ); + ret = 1; + } +#endif + } + + return( ret ); +} + +static char * +oc_check_required( Entry *e, char *ocname ) +{ + ObjectClass *oc; + AttributeType *at; + int i; + Attribute *a; + + 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 ) { + return( 0 ); + } + + /* check for empty oc_required */ + if(oc->soc_required == NULL) { + return( 0 ); + } + + /* for each required attribute */ + 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 ) { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + if( a->a_desc.ad_type == at ) { + break; + } +#else + char **pp; + + if ( at->sat_oid && + strcmp( a->a_type, at->sat_oid ) == 0 ) { + break; + } + pp = at->sat_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; + } +#endif + } + /* not there => schema violation */ + if ( a == NULL ) { + if ( at->sat_names && at->sat_names[0] ) { + return at->sat_names[0]; + } else { + return at->sat_oid; + } + } + } + + return( NULL ); +} + +static int +oc_check_allowed( char *type, struct berval **ocl ) +{ + ObjectClass *oc; + AttributeType *at; + int i, j; + char **pp; + char *p, *t; + + Debug( LDAP_DEBUG_TRACE, + "oc_check_allowed type \"%s\"\n", type, 0, 0 ); + + /* always allow objectclass attribute */ + if ( strcasecmp( type, "objectclass" ) == 0 ) { + return( 0 ); + } + +#ifndef SLAPD_SCHEMA_NOT_COMPAT + /* Treat any attribute type with option as an unknown attribute type */ + /* + * The "type" we have received is actually an AttributeDescription. + * Let's find out the corresponding type. + */ + p = strchr( type, ';' ); + if ( p ) { + t = ch_malloc( p-type+1 ); + strncpy( t, type, p-type ); + t[p-type] = '\0'; + Debug( LDAP_DEBUG_TRACE, + "oc_check_allowed type \"%s\" from \"%s\"\n", + t, type, 0 ); + + } else +#endif + { + t = type; + } + + + /* + * All operational attributions are allowed by schema rules. + */ + if ( oc_check_op_attr( t ) ) { + return( 0 ); + } + + /* check that the type appears as req or opt in at least one oc */ + for ( i = 0; ocl[i] != NULL; i++ ) { + /* if we know about the oc */ + if ( (oc = oc_find( ocl[i]->bv_val )) != NULL ) { + /* does it require the type? */ + for ( j = 0; oc->soc_required != NULL && + oc->soc_required[j] != NULL; j++ ) { + at = oc->soc_required[j]; + if ( at->sat_oid && + strcmp(at->sat_oid, t ) == 0 ) { + if ( t != type ) + ldap_memfree( t ); + return( 0 ); + } + pp = at->sat_names; + if ( pp == NULL ) + continue; + while ( *pp ) { + if ( strcasecmp( *pp, t ) == 0 ) { + if ( t != type ) + ldap_memfree( t ); + return( 0 ); + } + pp++; + } + } + /* does it allow the type? */ + for ( j = 0; oc->soc_allowed != NULL && + oc->soc_allowed[j] != NULL; j++ ) { + at = oc->soc_allowed[j]; + if ( at->sat_oid && + strcmp( at->sat_oid, t ) == 0 ) { + if ( t != type ) + ldap_memfree( t ); + return( 0 ); + } + pp = at->sat_names; + if ( pp == NULL ) + continue; + while ( *pp ) { + if ( strcasecmp( *pp, t ) == 0 || + strcmp( *pp, "*" ) == 0 ) { + if ( t != type ) + ldap_memfree( t ); + return( 0 ); + } + pp++; + } + } + /* maybe the next oc allows it */ + +#ifdef OC_UNDEFINED_IMPLES_EXTENSIBLE + /* we don't know about the oc. assume it allows it */ + } else { + if ( t != type ) + ldap_memfree( t ); + return( 0 ); +#endif + } + } + + if ( t != type ) + ldap_memfree( t ); + /* not allowed by any oc */ + return( 1 ); +} diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 35b864562f..8403bfc0f5 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -143,10 +143,10 @@ typedef int slap_syntax_transform_func LDAP_P(( typedef struct slap_syntax { LDAP_SYNTAX ssyn_syn; - int ssyn_flags; + unsigned ssyn_flags; -#define SLAP_SYNTAX_NONE 0 -#define SLAP_SYNTAX_BINARY 1 +#define SLAP_SYNTAX_NONE 0x0U +#define SLAP_SYNTAX_BINARY 0x1U slap_syntax_validate_func *ssyn_validate; @@ -210,6 +210,9 @@ typedef struct slap_matching_rule { } MatchingRule; typedef struct slap_attribute_type { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + char *sat_cname; +#endif LDAP_ATTRIBUTE_TYPE sat_atype; struct slap_attribute_type *sat_sup; struct slap_attribute_type **sat_subtypes; @@ -235,6 +238,11 @@ typedef struct slap_attribute_type { #define sat_usage sat_atype.at_usage } AttributeType; +#define is_at_operational(at) ((at)->sat_usage) +#define is_at_single_value(at) ((at)->sat_single_value) +#define is_at_collective(at) ((at)->sat_collective) +#define is_at_no_user_mod(at) ((at)->sat_no_user_mod) + typedef struct slap_object_class { LDAP_OBJECT_CLASS soc_oclass; struct slap_object_class **soc_sups; @@ -279,6 +287,32 @@ typedef struct slap_mra { struct berval *mra_value; } Mra; +#ifdef SLAPD_SCHEMA_NOT_COMPAT +/* + * represents a recognized attribute description ( type + options ) + */ +typedef struct slap_attr_desc { + struct berval *ad_cname; /* canonical name */ + AttributeType *ad_type; /* NULL if unknown */ + char *ad_lang; /* NULL if no language tags */ + unsigned ad_flags; +#define SLAP_DESC_NONE 0x0U +#define SLAP_DESC_BINARY 0x1U +} AttributeDescription; + +typedef struct slap_attr_assertion { + AttributeDescription aa_desc; + struct berval *aa_value; +} AttributeAssertion; + +typedef struct slap_mr_assertion { + char *ma_rule; /* optional */ + AttributeDescription *ma_desc; /* optional */ + int ma_dnattrs; /* boolean */ + struct berval *ma_value; /* required */ +} MatchingRuleAssertion; +#endif + /* * represents a search filter */ @@ -331,14 +365,16 @@ typedef struct slap_filter { } Filter; /* - * represents an attribute (type + values + syntax) + * represents an attribute (description + values) */ typedef struct slap_attr { +#ifdef SLAPD_SCHEMA_NOT_COMPAT + AttributeDescription a_desc; +#else char *a_type; /* description */ - struct berval **a_vals; -#ifndef SLAPD_SCHEMA_NOT_COMPAT int a_syntax; #endif + struct berval **a_vals; struct slap_attr *a_next; } Attribute; diff --git a/servers/slapd/syntax.c b/servers/slapd/syntax.c new file mode 100644 index 0000000000..e26fe835c5 --- /dev/null +++ b/servers/slapd/syntax.c @@ -0,0 +1,182 @@ +/* syntax.c - routines to manage syntax definitions */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include +#include + +#include "slap.h" +#include "ldap_pvt.h" + + +struct sindexrec { + char *sir_name; + Syntax *sir_syn; +}; + +static Avlnode *syn_index = NULL; +static Syntax *syn_list = NULL; + +static int +syn_index_cmp( + struct sindexrec *sir1, + struct sindexrec *sir2 +) +{ + return (strcmp( sir1->sir_name, sir2->sir_name )); +} + +static int +syn_index_name_cmp( + char *name, + struct sindexrec *sir +) +{ + return (strcmp( name, sir->sir_name )); +} + +Syntax * +syn_find( const char *synname ) +{ + struct sindexrec *sir = NULL; + + if ( (sir = (struct sindexrec *) avl_find( syn_index, synname, + (AVL_CMP) syn_index_name_cmp )) != NULL ) { + return( sir->sir_syn ); + } + return( NULL ); +} + +Syntax * +syn_find_desc( const char *syndesc, int *len ) +{ + Syntax *synp; + + for (synp = syn_list; synp; synp = synp->ssyn_next) + if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{'))) + return synp; + return( NULL ); +} + +static int +syn_insert( + Syntax *ssyn, + const char **err +) +{ + Syntax **synp; + struct sindexrec *sir; + + synp = &syn_list; + while ( *synp != NULL ) { + synp = &(*synp)->ssyn_next; + } + *synp = ssyn; + + if ( ssyn->ssyn_oid ) { + sir = (struct sindexrec *) + ch_calloc( 1, sizeof(struct sindexrec) ); + sir->sir_name = ssyn->ssyn_oid; + sir->sir_syn = ssyn; + if ( avl_insert( &syn_index, (caddr_t) sir, + (AVL_CMP) syn_index_cmp, + (AVL_DUP) avl_dup_error ) ) { + *err = ssyn->ssyn_oid; + ldap_memfree(sir); + return SLAP_SCHERR_DUP_SYNTAX; + } + /* FIX: temporal consistency check */ + syn_find(sir->sir_name); + } + return 0; +} + +int +syn_add( + LDAP_SYNTAX *syn, + int flags, + slap_syntax_validate_func *validate, + slap_syntax_transform_func *ber2str, + slap_syntax_transform_func *str2ber, + const char **err +) +{ + Syntax *ssyn; + int code; + + ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) ); + memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX)); + + ssyn->ssyn_flags = flags; + ssyn->ssyn_validate = validate; + ssyn->ssyn_ber2str = ber2str; + ssyn->ssyn_str2ber = str2ber; + + code = syn_insert(ssyn,err); + return code; +} + +int +register_syntax( + char * desc, int flags, + slap_syntax_validate_func *validate, + slap_syntax_transform_func *ber2str, + slap_syntax_transform_func *str2ber ) +{ + LDAP_SYNTAX *syn; + int code; + const char *err; + + syn = ldap_str2syntax( desc, &code, &err); + if ( !syn ) { + Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n", + ldap_scherr2str(code), err, desc ); + return( -1 ); + } + + code = syn_add( syn, flags, validate, ber2str, str2ber, &err ); + if ( code ) { + Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n", + scherr2str(code), err, desc ); + return( -1 ); + } + + return( 0 ); +} + +#if defined( SLAPD_SCHEMA_DN ) + +int +syn_schema_info( Entry *e ) +{ + struct berval val; + struct berval *vals[2]; + Syntax *syn; + + vals[0] = &val; + vals[1] = NULL; + + for ( syn = syn_list; syn; syn = syn->ssyn_next ) { + val.bv_val = ldap_syntax2str( &syn->ssyn_syn ); + if ( val.bv_val ) { + val.bv_len = strlen( val.bv_val ); + Debug( LDAP_DEBUG_TRACE, "Merging syn [%ld] %s\n", + (long) val.bv_len, val.bv_val, 0 ); + attr_merge( e, "ldapSyntaxes", vals ); + ldap_memfree( val.bv_val ); + } else { + return -1; + } + } + return 0; +} + +#endif diff --git a/servers/slapd/tools/Makefile.in b/servers/slapd/tools/Makefile.in index 17c9a94e17..f450db9f46 100644 --- a/servers/slapd/tools/Makefile.in +++ b/servers/slapd/tools/Makefile.in @@ -51,7 +51,8 @@ BDB2SRCS = QUIPUSRCS = edb2ldif.c ldapsyntax.c chlog2replog.c SLAPD_OBJS = ../config.o ../ch_malloc.o ../backend.o ../charray.o \ ../module.o ../aclparse.o ../filterentry.o \ - ../schema.o ../schema_init.o ../schemaparse.o \ + ../schema.o ../schema_check.o ../schema_init.o ../schemaparse.o \ + ../at.o ../mr.o ../oc.o ../syntax.o \ ../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \ ../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \ ../controls.o ../kerberos.o ../passwd.o \ diff --git a/servers/slapd/tools/slapadd.c b/servers/slapd/tools/slapadd.c index 73a4b7656a..0acdbdf453 100644 --- a/servers/slapd/tools/slapadd.c +++ b/servers/slapd/tools/slapadd.c @@ -69,7 +69,7 @@ main( int argc, char **argv ) } /* check schema */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + if ( schema_check_entry( e ) != 0 ) { fprintf( stderr, "%s: schema violation in entry dn=\"%s\" (line=%d)\n", progname, e->e_dn, lineno ); rc = EXIT_FAILURE; -- 2.39.5