1 /* cr.c - content rule routines */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/cr.c,v 1.22.2.3 2008/02/11 23:26:44 kurt 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>
28 struct berval cir_name
;
32 static Avlnode
*cr_index
= NULL
;
33 static LDAP_STAILQ_HEAD(CRList
, ContentRule
) cr_list
34 = LDAP_STAILQ_HEAD_INITIALIZER(cr_list
);
41 const struct cindexrec
*cir1
= v_cir1
;
42 const struct cindexrec
*cir2
= v_cir2
;
43 int i
= cir1
->cir_name
.bv_len
- cir2
->cir_name
.bv_len
;
45 return strcasecmp( cir1
->cir_name
.bv_val
, cir2
->cir_name
.bv_val
);
53 const struct berval
*name
= v_name
;
54 const struct cindexrec
*cir
= v_cir
;
55 int i
= name
->bv_len
- cir
->cir_name
.bv_len
;
57 return strncasecmp( name
->bv_val
, cir
->cir_name
.bv_val
, name
->bv_len
);
61 cr_find( const char *crname
)
65 bv
.bv_val
= (char *)crname
;
66 bv
.bv_len
= strlen( crname
);
68 return( cr_bvfind( &bv
) );
72 cr_bvfind( struct berval
*crname
)
74 struct cindexrec
*cir
;
76 cir
= avl_find( cr_index
, crname
, cr_index_name_cmp
);
79 return( cir
->cir_cr
);
86 cr_destroy_one( ContentRule
*c
)
90 if (c
->scr_auxiliaries
) ldap_memfree(c
->scr_auxiliaries
);
91 if (c
->scr_required
) ldap_memfree(c
->scr_required
);
92 if (c
->scr_allowed
) ldap_memfree(c
->scr_allowed
);
93 if (c
->scr_precluded
) ldap_memfree(c
->scr_precluded
);
94 ldap_contentrule_free((LDAPContentRule
*)c
);
104 avl_free(cr_index
, ldap_memfree
);
106 while( !LDAP_STAILQ_EMPTY(&cr_list
) ) {
107 c
= LDAP_STAILQ_FIRST(&cr_list
);
108 LDAP_STAILQ_REMOVE_HEAD(&cr_list
, scr_next
);
120 struct cindexrec
*cir
;
123 if ( scr
->scr_oid
) {
124 cir
= (struct cindexrec
*)
125 ch_calloc( 1, sizeof(struct cindexrec
) );
126 cir
->cir_name
.bv_val
= scr
->scr_oid
;
127 cir
->cir_name
.bv_len
= strlen( scr
->scr_oid
);
130 assert( cir
->cir_name
.bv_val
!= NULL
);
131 assert( cir
->cir_cr
!= NULL
);
133 if ( avl_insert( &cr_index
, (caddr_t
) cir
,
134 cr_index_cmp
, avl_dup_error
) )
138 return SLAP_SCHERR_CR_DUP
;
141 /* FIX: temporal consistency check */
142 assert( cr_bvfind(&cir
->cir_name
) != NULL
);
145 if ( (names
= scr
->scr_names
) ) {
147 cir
= (struct cindexrec
*)
148 ch_calloc( 1, sizeof(struct cindexrec
) );
149 cir
->cir_name
.bv_val
= *names
;
150 cir
->cir_name
.bv_len
= strlen( *names
);
153 assert( cir
->cir_name
.bv_val
!= NULL
);
154 assert( cir
->cir_cr
!= NULL
);
156 if ( avl_insert( &cr_index
, (caddr_t
) cir
,
157 cr_index_cmp
, avl_dup_error
) )
161 return SLAP_SCHERR_CR_DUP
;
164 /* FIX: temporal consistency check */
165 assert( cr_bvfind(&cir
->cir_name
) != NULL
);
171 LDAP_STAILQ_INSERT_TAIL(&cr_list
, scr
, scr_next
);
184 if( scr
->scr_oc_oids_aux
== NULL
) return 0;
186 for( naux
=0; scr
->scr_oc_oids_aux
[naux
]; naux
++ ) {
190 scr
->scr_auxiliaries
= ch_calloc( naux
+1, sizeof(ObjectClass
*));
192 for( naux
=0; scr
->scr_oc_oids_aux
[naux
]; naux
++ ) {
193 ObjectClass
*soc
= scr
->scr_auxiliaries
[naux
]
194 = oc_find(scr
->scr_oc_oids_aux
[naux
]);
196 *err
= scr
->scr_oc_oids_aux
[naux
];
197 return SLAP_SCHERR_CLASS_NOT_FOUND
;
200 if( soc
->soc_flags
& SLAP_OC_OPERATIONAL
&&
201 soc
!= slap_schema
.si_oc_extensibleObject
)
206 if( soc
->soc_kind
!= LDAP_SCHEMA_AUXILIARY
) {
207 *err
= scr
->scr_oc_oids_aux
[naux
];
208 return SLAP_SCHERR_CR_BAD_AUX
;
212 scr
->scr_auxiliaries
[naux
] = NULL
;
222 char **attrs
= scr
->scr_at_oids_must
;
229 sat
= at_find(*attrs1
);
232 return SLAP_SCHERR_ATTR_NOT_FOUND
;
235 if( is_at_operational( sat
)) (*op
)++;
237 if ( at_find_in_list(sat
, scr
->scr_required
) < 0) {
238 if ( at_append_to_list(sat
, &scr
->scr_required
) ) {
240 return SLAP_SCHERR_OUTOFMEM
;
244 return SLAP_SCHERR_CR_BAD_AT
;
258 char **attrs
= scr
->scr_at_oids_may
;
265 sat
= at_find(*attrs1
);
268 return SLAP_SCHERR_ATTR_NOT_FOUND
;
271 if( is_at_operational( sat
)) (*op
)++;
273 if ( at_find_in_list(sat
, scr
->scr_required
) < 0 &&
274 at_find_in_list(sat
, scr
->scr_allowed
) < 0 )
276 if ( at_append_to_list(sat
, &scr
->scr_allowed
) ) {
278 return SLAP_SCHERR_OUTOFMEM
;
282 return SLAP_SCHERR_CR_BAD_AT
;
296 char **attrs
= scr
->scr_at_oids_not
;
303 sat
= at_find(*attrs1
);
306 return SLAP_SCHERR_ATTR_NOT_FOUND
;
309 if( is_at_operational( sat
)) (*op
)++;
311 /* FIXME: should also make sure attribute type is not
312 a required attribute of the structural class or
313 any auxiliary class */
314 if ( at_find_in_list(sat
, scr
->scr_required
) < 0 &&
315 at_find_in_list(sat
, scr
->scr_allowed
) < 0 &&
316 at_find_in_list(sat
, scr
->scr_precluded
) < 0 )
318 if ( at_append_to_list(sat
, &scr
->scr_precluded
) ) {
320 return SLAP_SCHERR_OUTOFMEM
;
324 return SLAP_SCHERR_CR_BAD_AT
;
345 if ( cr
->cr_names
!= NULL
) {
348 for( i
=0; cr
->cr_names
[i
]; i
++ ) {
349 if( !slap_valid_descr( cr
->cr_names
[i
] ) ) {
350 return SLAP_SCHERR_BAD_DESCR
;
355 if ( !OID_LEADCHAR( cr
->cr_oid
[0] )) {
356 /* Expand OID macros */
357 char *oid
= oidm_find( cr
->cr_oid
);
360 return SLAP_SCHERR_OIDM
;
362 if ( oid
!= cr
->cr_oid
) {
368 scr
= (ContentRule
*) ch_calloc( 1, sizeof(ContentRule
) );
369 AC_MEMCPY( &scr
->scr_crule
, cr
, sizeof(LDAPContentRule
) );
371 scr
->scr_oidmacro
= oidm
;
372 scr
->scr_sclass
= oc_find(cr
->cr_oid
);
373 if ( !scr
->scr_sclass
) {
375 code
= SLAP_SCHERR_CLASS_NOT_FOUND
;
379 /* check object class usage */
380 if( scr
->scr_sclass
->soc_kind
!= LDAP_SCHEMA_STRUCTURAL
)
383 code
= SLAP_SCHERR_CR_BAD_STRUCT
;
387 if( scr
->scr_sclass
->soc_flags
& SLAP_OC_OPERATIONAL
) op
++;
389 code
= cr_add_auxiliaries( scr
, &op
, err
);
390 if ( code
!= 0 ) goto fail
;
392 code
= cr_create_required( scr
, &op
, err
);
393 if ( code
!= 0 ) goto fail
;
395 code
= cr_create_allowed( scr
, &op
, err
);
396 if ( code
!= 0 ) goto fail
;
398 code
= cr_create_precluded( scr
, &op
, err
);
399 if ( code
!= 0 ) goto fail
;
402 code
= SLAP_SCHERR_CR_BAD_AUX
;
406 code
= cr_insert(scr
,err
);
407 if ( code
== 0 && rscr
)
416 cr_unparse( BerVarray
*res
, ContentRule
*start
, ContentRule
*end
, int sys
)
420 struct berval bv
, *bva
= NULL
, idx
;
424 start
= LDAP_STAILQ_FIRST( &cr_list
);
426 /* count the result size */
428 for ( cr
=start
; cr
; cr
=LDAP_STAILQ_NEXT(cr
, scr_next
)) {
429 if ( sys
&& !(cr
->scr_flags
& SLAP_CR_HARDCODE
)) continue;
431 if ( cr
== end
) break;
436 bva
= ch_malloc( (num
+1) * sizeof(struct berval
) );
444 for ( cr
=start
; cr
; cr
=LDAP_STAILQ_NEXT(cr
, scr_next
)) {
445 LDAPContentRule lcr
, *lcrp
;
446 if ( sys
&& !(cr
->scr_flags
& SLAP_CR_HARDCODE
)) continue;
447 if ( cr
->scr_oidmacro
) {
449 lcr
.cr_oid
= cr
->scr_oidmacro
;
452 lcrp
= &cr
->scr_crule
;
454 if ( ldap_contentrule2bv( lcrp
, &bv
) == NULL
) {
455 ber_bvarray_free( bva
);
458 idx
.bv_len
= sprintf(idx
.bv_val
, "{%d}", i
);
460 bva
[i
].bv_len
= idx
.bv_len
+ bv
.bv_len
;
461 bva
[i
].bv_val
= ch_malloc( bva
[i
].bv_len
+ 1 );
462 strcpy( bva
[i
].bv_val
, ibuf
);
463 strcpy( bva
[i
].bv_val
+ idx
.bv_len
, bv
.bv_val
);
465 bva
[i
].bv_val
= NULL
;
466 ldap_memfree( bv
.bv_val
);
467 if ( cr
== end
) break;
473 cr_schema_info( Entry
*e
)
475 AttributeDescription
*ad_ditContentRules
476 = slap_schema
.si_ad_ditContentRules
;
482 LDAP_STAILQ_FOREACH(cr
, &cr_list
, scr_next
) {
483 if ( ldap_contentrule2bv( &cr
->scr_crule
, &val
) == NULL
) {
488 if( cr
->scr_flags
& SLAP_CR_HIDE
) continue;
491 Debug( LDAP_DEBUG_TRACE
, "Merging cr [%ld] %s\n",
492 (long) val
.bv_len
, val
.bv_val
, 0 );
495 nval
.bv_val
= cr
->scr_oid
;
496 nval
.bv_len
= strlen(cr
->scr_oid
);
498 if( attr_merge_one( e
, ad_ditContentRules
, &val
, &nval
) )
502 ldap_memfree( val
.bv_val
);