1 /* oc.c - object class routines */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/oc.c,v 1.77.2.6 2008/04/14 22:08:32 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
22 #include <ac/string.h>
23 #include <ac/socket.h>
27 int is_object_subclass(
33 if( sub
== NULL
|| sup
== NULL
) return 0;
36 Debug( LDAP_DEBUG_TRACE
, "is_object_subclass(%s,%s) %d\n",
37 sup
->soc_oid
, sub
->soc_oid
, sup
== sub
);
44 if ( sub
->soc_sups
== NULL
) {
48 for ( i
= 0; sub
->soc_sups
[i
] != NULL
; i
++ ) {
49 if ( is_object_subclass( sup
, sub
->soc_sups
[i
] ) ) {
57 int is_entry_objectclass(
63 * set_flags should only be true if oc is one of operational
64 * object classes which we support objectClass flags for
65 * (e.g., referral, alias, ...). See <slap.h>.
71 assert( !( e
== NULL
|| oc
== NULL
) );
72 assert( ( flags
& SLAP_OCF_MASK
) != SLAP_OCF_MASK
);
74 if ( e
== NULL
|| oc
== NULL
) {
78 if ( flags
== SLAP_OCF_SET_FLAGS
&& ( e
->e_ocflags
& SLAP_OC__END
) )
80 /* flags are set, use them */
81 return (e
->e_ocflags
& oc
->soc_flags
& SLAP_OC__MASK
) != 0;
85 * find objectClass attribute
87 attr
= attr_find( e
->e_attrs
, slap_schema
.si_ad_objectClass
);
89 /* no objectClass attribute */
90 Debug( LDAP_DEBUG_ANY
, "is_entry_objectclass(\"%s\", \"%s\") "
91 "no objectClass attribute\n",
92 e
->e_dn
== NULL
? "" : e
->e_dn
,
93 oc
->soc_oclass
.oc_oid
, 0 );
98 for ( bv
= attr
->a_vals
; bv
->bv_val
; bv
++ ) {
99 ObjectClass
*objectClass
= oc_bvfind( bv
);
101 if ( objectClass
== NULL
) {
102 /* FIXME: is this acceptable? */
106 if ( !( flags
& SLAP_OCF_SET_FLAGS
) ) {
107 if ( objectClass
== oc
) {
111 if ( ( flags
& SLAP_OCF_CHECK_SUP
)
112 && is_object_subclass( oc
, objectClass
) )
118 e
->e_ocflags
|= objectClass
->soc_flags
;
121 /* mark flags as set */
122 e
->e_ocflags
|= SLAP_OC__END
;
124 return ( e
->e_ocflags
& oc
->soc_flags
& SLAP_OC__MASK
) != 0;
129 struct berval oir_name
;
133 static Avlnode
*oc_index
= NULL
;
134 static Avlnode
*oc_cache
= NULL
;
135 static LDAP_STAILQ_HEAD(OCList
, ObjectClass
) oc_list
136 = LDAP_STAILQ_HEAD_INITIALIZER(oc_list
);
138 ObjectClass
*oc_sys_tail
;
145 const struct oindexrec
*oir1
= v_oir1
, *oir2
= v_oir2
;
146 int i
= oir1
->oir_name
.bv_len
- oir2
->oir_name
.bv_len
;
148 return strcasecmp( oir1
->oir_name
.bv_val
, oir2
->oir_name
.bv_val
);
156 const struct berval
*name
= v_name
;
157 const struct oindexrec
*oir
= v_oir
;
158 int i
= name
->bv_len
- oir
->oir_name
.bv_len
;
160 return strncasecmp( name
->bv_val
, oir
->oir_name
.bv_val
, name
->bv_len
);
164 oc_find( const char *ocname
)
168 bv
.bv_val
= (char *)ocname
;
169 bv
.bv_len
= strlen( ocname
);
171 return( oc_bvfind( &bv
) );
175 oc_bvfind( struct berval
*ocname
)
177 struct oindexrec
*oir
;
180 oir
= avl_find( oc_cache
, ocname
, oc_index_name_cmp
);
181 if ( oir
) return oir
->oir_oc
;
183 oir
= avl_find( oc_index
, ocname
, oc_index_name_cmp
);
187 avl_insert( &oc_cache
, (caddr_t
) oir
,
188 oc_index_cmp
, avl_dup_error
);
190 return( oir
->oir_oc
);
196 static LDAP_STAILQ_HEAD(OCUList
, ObjectClass
) oc_undef_list
197 = LDAP_STAILQ_HEAD_INITIALIZER(oc_undef_list
);
200 oc_bvfind_undef( struct berval
*ocname
)
202 ObjectClass
*oc
= oc_bvfind( ocname
);
208 LDAP_STAILQ_FOREACH( oc
, &oc_undef_list
, soc_next
) {
209 int d
= oc
->soc_cname
.bv_len
- ocname
->bv_len
;
215 if ( strcasecmp( oc
->soc_cname
.bv_val
, ocname
->bv_val
) == 0 ) {
224 oc
= ch_malloc( sizeof( ObjectClass
) + ocname
->bv_len
+ 1 );
225 memset( oc
, 0, sizeof( ObjectClass
) );
227 oc
->soc_cname
.bv_len
= ocname
->bv_len
;
228 oc
->soc_cname
.bv_val
= (char *)&oc
[ 1 ];
229 AC_MEMCPY( oc
->soc_cname
.bv_val
, ocname
->bv_val
, ocname
->bv_len
);
231 LDAP_STAILQ_NEXT( oc
, soc_next
) = NULL
;
232 ldap_pvt_thread_mutex_lock( &oc_undef_mutex
);
233 LDAP_STAILQ_INSERT_HEAD( &oc_undef_list
, oc
, soc_next
);
234 ldap_pvt_thread_mutex_unlock( &oc_undef_mutex
);
248 AttributeType
**satp
;
254 sat
= at_find(*attrs1
);
257 return SLAP_SCHERR_ATTR_NOT_FOUND
;
260 if( is_at_operational( sat
)) (*op
)++;
262 if ( at_find_in_list(sat
, soc
->soc_required
) < 0) {
263 if ( at_append_to_list(sat
, &soc
->soc_required
) ) {
265 return SLAP_SCHERR_OUTOFMEM
;
270 /* Now delete duplicates from the allowed list */
271 for ( satp
= soc
->soc_required
; *satp
; satp
++ ) {
272 i
= at_find_in_list(*satp
, soc
->soc_allowed
);
274 at_delete_from_list(i
, &soc
->soc_allowed
);
294 sat
= at_find(*attrs1
);
297 return SLAP_SCHERR_ATTR_NOT_FOUND
;
300 if( is_at_operational( sat
)) (*op
)++;
302 if ( at_find_in_list(sat
, soc
->soc_required
) < 0 &&
303 at_find_in_list(sat
, soc
->soc_allowed
) < 0 ) {
304 if ( at_append_to_list(sat
, &soc
->soc_allowed
) ) {
306 return SLAP_SCHERR_OUTOFMEM
;
329 if ( !soc
->soc_sups
) {
330 /* We are at the first recursive level */
338 soc
->soc_sups
= (ObjectClass
**)ch_calloc(nsups
,
339 sizeof(ObjectClass
*));
345 soc1
= oc_find(*sups1
);
348 return SLAP_SCHERR_CLASS_NOT_FOUND
;
351 /* check object class usage
352 * abstract classes can only sup abstract classes
353 * structural classes can not sup auxiliary classes
354 * auxiliary classes can not sup structural classes
356 if( soc
->soc_kind
!= soc1
->soc_kind
357 && soc1
->soc_kind
!= LDAP_SCHEMA_ABSTRACT
)
360 return SLAP_SCHERR_CLASS_BAD_SUP
;
363 if( soc1
->soc_obsolete
&& !soc
->soc_obsolete
) {
365 return SLAP_SCHERR_CLASS_BAD_SUP
;
368 if( soc
->soc_flags
& SLAP_OC_OPERATIONAL
) (*op
)++;
371 soc
->soc_sups
[nsups
] = soc1
;
374 code
= oc_add_sups( soc
, soc1
->soc_sup_oids
, op
, err
);
375 if ( code
) return code
;
377 code
= oc_create_required( soc
, soc1
->soc_at_oids_must
, op
, err
);
378 if ( code
) return code
;
380 code
= oc_create_allowed( soc
, soc1
->soc_at_oids_may
, op
, err
);
381 if ( code
) return code
;
392 oc_delete_names( ObjectClass
*oc
)
394 char **names
= oc
->soc_names
;
397 struct oindexrec tmpoir
, *oir
;
399 ber_str2bv( *names
, 0, 0, &tmpoir
.oir_name
);
401 oir
= (struct oindexrec
*)avl_delete( &oc_index
,
402 (caddr_t
)&tmpoir
, oc_index_cmp
);
403 assert( oir
!= NULL
);
409 /* Mark the ObjectClass as deleted, remove from list, and remove all its
410 * names from the AVL tree. Leave the OID in the tree.
413 oc_delete( ObjectClass
*oc
)
415 oc
->soc_flags
|= SLAP_OC_DELETED
;
417 LDAP_STAILQ_REMOVE(&oc_list
, oc
, ObjectClass
, soc_next
);
419 oc_delete_names( oc
);
423 oc_clean( ObjectClass
*o
)
426 ldap_memfree(o
->soc_sups
);
429 if (o
->soc_required
) {
430 ldap_memfree(o
->soc_required
);
431 o
->soc_required
= NULL
;
433 if (o
->soc_allowed
) {
434 ldap_memfree(o
->soc_allowed
);
435 o
->soc_allowed
= NULL
;
437 if (o
->soc_oidmacro
) {
438 ldap_memfree(o
->soc_oidmacro
);
439 o
->soc_oidmacro
= NULL
;
444 oc_destroy_one( void *v
)
446 struct oindexrec
*oir
= v
;
447 ObjectClass
*o
= oir
->oir_oc
;
450 ldap_objectclass_free((LDAPObjectClass
*)o
);
459 while( !LDAP_STAILQ_EMPTY(&oc_list
) ) {
460 o
= LDAP_STAILQ_FIRST(&oc_list
);
461 LDAP_STAILQ_REMOVE_HEAD(&oc_list
, soc_next
);
463 oc_delete_names( o
);
466 avl_free( oc_index
, oc_destroy_one
);
468 while( !LDAP_STAILQ_EMPTY(&oc_undef_list
) ) {
469 o
= LDAP_STAILQ_FIRST(&oc_undef_list
);
470 LDAP_STAILQ_REMOVE_HEAD(&oc_undef_list
, soc_next
);
472 ch_free( (ObjectClass
*)o
);
477 oc_start( ObjectClass
**oc
)
479 assert( oc
!= NULL
);
481 *oc
= LDAP_STAILQ_FIRST(&oc_list
);
483 return (*oc
!= NULL
);
487 oc_next( ObjectClass
**oc
)
489 assert( oc
!= NULL
);
491 #if 0 /* pedantic check: breaks when deleting an oc, don't use it. */
493 ObjectClass
*tmp
= NULL
;
495 LDAP_STAILQ_FOREACH(tmp
,&oc_list
,soc_next
) {
501 assert( tmp
!= NULL
);
509 *oc
= LDAP_STAILQ_NEXT(*oc
,soc_next
);
511 return (*oc
!= NULL
);
515 * check whether the two ObjectClasses actually __are__ identical,
516 * or rather inconsistent
521 ObjectClass
*new_soc
)
523 if ( new_soc
->soc_oid
!= NULL
) {
524 if ( soc
->soc_oid
== NULL
) {
525 return SLAP_SCHERR_CLASS_INCONSISTENT
;
528 if ( strcmp( soc
->soc_oid
, new_soc
->soc_oid
) != 0 ) {
529 return SLAP_SCHERR_CLASS_INCONSISTENT
;
533 if ( soc
->soc_oid
!= NULL
) {
534 return SLAP_SCHERR_CLASS_INCONSISTENT
;
538 if ( new_soc
->soc_names
) {
541 if ( soc
->soc_names
== NULL
) {
542 return SLAP_SCHERR_CLASS_INCONSISTENT
;
545 for ( i
= 0; new_soc
->soc_names
[ i
]; i
++ ) {
546 if ( soc
->soc_names
[ i
] == NULL
) {
547 return SLAP_SCHERR_CLASS_INCONSISTENT
;
550 if ( strcasecmp( soc
->soc_names
[ i
],
551 new_soc
->soc_names
[ i
] ) != 0 )
553 return SLAP_SCHERR_CLASS_INCONSISTENT
;
557 if ( soc
->soc_names
!= NULL
) {
558 return SLAP_SCHERR_CLASS_INCONSISTENT
;
562 return SLAP_SCHERR_CLASS_DUP
;
565 static struct oindexrec
*oir_old
;
568 oc_dup_error( void *left
, void *right
)
580 struct oindexrec
*oir
;
582 ObjectClass
*soc
= *roc
;
584 if ( soc
->soc_oid
) {
585 oir
= (struct oindexrec
*)
586 ch_calloc( 1, sizeof(struct oindexrec
) );
587 ber_str2bv( soc
->soc_oid
, 0, 0, &oir
->oir_name
);
591 if ( avl_insert( &oc_index
, (caddr_t
) oir
,
592 oc_index_cmp
, oc_dup_error
) )
594 ObjectClass
*old_soc
;
599 assert( oir_old
!= NULL
);
600 old_soc
= oir_old
->oir_oc
;
602 /* replacing a deleted definition? */
603 if ( old_soc
->soc_flags
& SLAP_OC_DELETED
) {
606 /* Keep old oid, free new oid;
607 * Keep new everything else, free old
611 old_soc
->soc_oid
= tmp
.soc_oid
;
612 tmp
.soc_oid
= soc
->soc_oid
;
616 oc_destroy_one( oir
);
622 rc
= oc_check_dup( old_soc
, soc
);
629 /* FIX: temporal consistency check */
630 assert( oc_bvfind( &oir
->oir_name
) != NULL
);
633 if ( (names
= soc
->soc_names
) ) {
635 oir
= (struct oindexrec
*)
636 ch_calloc( 1, sizeof(struct oindexrec
) );
637 oir
->oir_name
.bv_val
= *names
;
638 oir
->oir_name
.bv_len
= strlen( *names
);
641 assert( oir
->oir_name
.bv_val
!= NULL
);
642 assert( oir
->oir_oc
!= NULL
);
644 if ( avl_insert( &oc_index
, (caddr_t
) oir
,
645 oc_index_cmp
, avl_dup_error
) )
647 ObjectClass
*old_soc
;
652 old_soc
= oc_bvfind( &oir
->oir_name
);
653 assert( old_soc
!= NULL
);
654 rc
= oc_check_dup( old_soc
, soc
);
658 while ( names
> soc
->soc_names
) {
659 struct oindexrec tmpoir
;
662 ber_str2bv( *names
, 0, 0, &tmpoir
.oir_name
);
664 oir
= (struct oindexrec
*)avl_delete( &oc_index
,
665 (caddr_t
)&tmpoir
, oc_index_cmp
);
666 assert( oir
!= NULL
);
670 if ( soc
->soc_oid
) {
671 struct oindexrec tmpoir
;
673 ber_str2bv( soc
->soc_oid
, 0, 0, &tmpoir
.oir_name
);
675 oir
= (struct oindexrec
*)avl_delete( &oc_index
,
676 (caddr_t
)&tmpoir
, oc_index_cmp
);
677 assert( oir
!= NULL
);
684 /* FIX: temporal consistency check */
685 assert( oc_bvfind(&oir
->oir_name
) != NULL
);
690 if ( soc
->soc_flags
& SLAP_OC_HARDCODE
) {
695 LDAP_STAILQ_INSERT_AFTER( &oc_list
, prev
, soc
, soc_next
);
697 LDAP_STAILQ_INSERT_TAIL( &oc_list
, soc
, soc_next
);
716 if ( oc
->oc_names
!= NULL
) {
719 for( i
=0; oc
->oc_names
[i
]; i
++ ) {
720 if( !slap_valid_descr( oc
->oc_names
[i
] ) ) {
721 return SLAP_SCHERR_BAD_DESCR
;
726 if ( !OID_LEADCHAR( oc
->oc_oid
[0] )) {
727 /* Expand OID macros */
728 char *oid
= oidm_find( oc
->oc_oid
);
731 return SLAP_SCHERR_OIDM
;
733 if ( oid
!= oc
->oc_oid
) {
739 soc
= (ObjectClass
*) ch_calloc( 1, sizeof(ObjectClass
) );
740 AC_MEMCPY( &soc
->soc_oclass
, oc
, sizeof(LDAPObjectClass
) );
742 soc
->soc_oidmacro
= oidm
;
743 if( oc
->oc_names
!= NULL
) {
744 soc
->soc_cname
.bv_val
= soc
->soc_names
[0];
746 soc
->soc_cname
.bv_val
= soc
->soc_oid
;
748 soc
->soc_cname
.bv_len
= strlen( soc
->soc_cname
.bv_val
);
750 if( soc
->soc_sup_oids
== NULL
&&
751 soc
->soc_kind
== LDAP_SCHEMA_STRUCTURAL
)
753 /* structural object classes implicitly inherit from 'top' */
754 static char *top_oids
[] = { SLAPD_TOP_OID
, NULL
};
755 code
= oc_add_sups( soc
, top_oids
, &op
, err
);
757 code
= oc_add_sups( soc
, soc
->soc_sup_oids
, &op
, err
);
765 code
= SLAP_SCHERR_CLASS_BAD_SUP
;
769 code
= oc_create_required( soc
, soc
->soc_at_oids_must
, &op
, err
);
774 code
= oc_create_allowed( soc
, soc
->soc_at_oids_may
, &op
, err
);
780 code
= SLAP_SCHERR_CLASS_BAD_USAGE
;
785 soc
->soc_flags
|= SLAP_OC_HARDCODE
;
788 code
= oc_insert(&soc
,prev
,err
);
791 if ( soc
->soc_sups
) {
792 ch_free( soc
->soc_sups
);
795 if ( soc
->soc_required
) {
796 ch_free( soc
->soc_required
);
799 if ( soc
->soc_allowed
) {
800 ch_free( soc
->soc_allowed
);
812 oc_unparse( BerVarray
*res
, ObjectClass
*start
, ObjectClass
*end
, int sys
)
816 struct berval bv
, *bva
= NULL
, idx
;
820 start
= LDAP_STAILQ_FIRST( &oc_list
);
822 /* count the result size */
824 for ( oc
=start
; oc
; oc
=LDAP_STAILQ_NEXT(oc
, soc_next
)) {
825 if ( sys
&& !(oc
->soc_flags
& SLAP_OC_HARDCODE
)) break;
827 if ( oc
== end
) break;
832 bva
= ch_malloc( (num
+1) * sizeof(struct berval
) );
840 for ( oc
=start
; oc
; oc
=LDAP_STAILQ_NEXT(oc
, soc_next
)) {
841 LDAPObjectClass loc
, *locp
;
842 if ( sys
&& !(oc
->soc_flags
& SLAP_OC_HARDCODE
)) break;
843 if ( oc
->soc_oidmacro
) {
844 loc
= oc
->soc_oclass
;
845 loc
.oc_oid
= oc
->soc_oidmacro
;
848 locp
= &oc
->soc_oclass
;
850 if ( ldap_objectclass2bv( locp
, &bv
) == NULL
) {
851 ber_bvarray_free( bva
);
854 idx
.bv_len
= sprintf(idx
.bv_val
, "{%d}", i
);
856 bva
[i
].bv_len
= idx
.bv_len
+ bv
.bv_len
;
857 bva
[i
].bv_val
= ch_malloc( bva
[i
].bv_len
+ 1 );
858 strcpy( bva
[i
].bv_val
, ibuf
);
859 strcpy( bva
[i
].bv_val
+ idx
.bv_len
, bv
.bv_val
);
861 bva
[i
].bv_val
= NULL
;
862 ldap_memfree( bv
.bv_val
);
863 if ( oc
== end
) break;
869 oc_schema_info( Entry
*e
)
871 AttributeDescription
*ad_objectClasses
= slap_schema
.si_ad_objectClasses
;
876 LDAP_STAILQ_FOREACH( oc
, &oc_list
, soc_next
) {
877 if( oc
->soc_flags
& SLAP_OC_HIDE
) continue;
879 if ( ldap_objectclass2bv( &oc
->soc_oclass
, &val
) == NULL
) {
883 nval
= oc
->soc_cname
;
886 Debug( LDAP_DEBUG_TRACE
, "Merging oc [%ld] %s (%s)\n",
887 (long) val
.bv_len
, val
.bv_val
, nval
.bv_val
);
890 if( attr_merge_one( e
, ad_objectClasses
, &val
, &nval
) ) {
893 ldap_memfree( val
.bv_val
);
899 register_oc( const char *def
, ObjectClass
**soc
, int dupok
)
905 oc
= ldap_str2objectclass( def
, &code
, &err
, LDAP_SCHEMA_ALLOW_ALL
);
907 Debug( LDAP_DEBUG_ANY
,
908 "register_oc: objectclass \"%s\": %s, %s\n",
909 def
, ldap_scherr2str(code
), err
);
912 code
= oc_add(oc
,0,NULL
,NULL
,&err
);
913 if ( code
&& ( code
!= SLAP_SCHERR_CLASS_DUP
|| !dupok
)) {
914 Debug( LDAP_DEBUG_ANY
,
915 "register_oc: objectclass \"%s\": %s, %s\n",
916 def
, scherr2str(code
), err
);
917 ldap_objectclass_free(oc
);
921 *soc
= oc_find(oc
->oc_names
[0]);
923 ldap_objectclass_free(oc
);