mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-24 13:24:56 +08:00
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.
This commit is contained in:
parent
86cedc6ac7
commit
f9195f9b6f
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
563
servers/slapd/at.c
Normal file
563
servers/slapd/at.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/errno.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#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 <name>+ <syntax>\" (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
|
@ -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 <name>+ <syntax>\" (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
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
@ -197,9 +197,18 @@ entry2str(
|
||||
/* put "<type>:[:] <value>" 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 );
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
206
servers/slapd/mr.c
Normal file
206
servers/slapd/mr.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#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
|
456
servers/slapd/oc.c
Normal file
456
servers/slapd/oc.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#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
|
@ -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
|
||||
|
@ -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, /*{{{*/ "}}}" );
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
271
servers/slapd/schema_check.c
Normal file
271
servers/slapd/schema_check.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#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 );
|
||||
}
|
@ -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;
|
||||
|
||||
|
182
servers/slapd/syntax.c
Normal file
182
servers/slapd/syntax.c
Normal file
@ -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 <stdio.h>
|
||||
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#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
|
@ -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 \
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user