1*2de962bdSlukem /* cr.c - content rule routines */
2*2de962bdSlukem /* $OpenLDAP: pkg/ldap/servers/slapd/cr.c,v 1.22.2.3 2008/02/11 23:26:44 kurt Exp $ */
3*2de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4*2de962bdSlukem  *
5*2de962bdSlukem  * Copyright 1998-2008 The OpenLDAP Foundation.
6*2de962bdSlukem  * All rights reserved.
7*2de962bdSlukem  *
8*2de962bdSlukem  * Redistribution and use in source and binary forms, with or without
9*2de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
10*2de962bdSlukem  * Public License.
11*2de962bdSlukem  *
12*2de962bdSlukem  * A copy of this license is available in the file LICENSE in the
13*2de962bdSlukem  * top-level directory of the distribution or, alternatively, at
14*2de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
15*2de962bdSlukem  */
16*2de962bdSlukem 
17*2de962bdSlukem #include "portable.h"
18*2de962bdSlukem 
19*2de962bdSlukem #include <stdio.h>
20*2de962bdSlukem 
21*2de962bdSlukem #include <ac/ctype.h>
22*2de962bdSlukem #include <ac/string.h>
23*2de962bdSlukem #include <ac/socket.h>
24*2de962bdSlukem 
25*2de962bdSlukem #include "slap.h"
26*2de962bdSlukem 
27*2de962bdSlukem struct cindexrec {
28*2de962bdSlukem 	struct berval	cir_name;
29*2de962bdSlukem 	ContentRule	*cir_cr;
30*2de962bdSlukem };
31*2de962bdSlukem 
32*2de962bdSlukem static Avlnode	*cr_index = NULL;
33*2de962bdSlukem static LDAP_STAILQ_HEAD(CRList, ContentRule) cr_list
34*2de962bdSlukem 	= LDAP_STAILQ_HEAD_INITIALIZER(cr_list);
35*2de962bdSlukem 
36*2de962bdSlukem static int
37*2de962bdSlukem cr_index_cmp(
38*2de962bdSlukem     const void	*v_cir1,
39*2de962bdSlukem     const void	*v_cir2 )
40*2de962bdSlukem {
41*2de962bdSlukem 	const struct cindexrec	*cir1 = v_cir1;
42*2de962bdSlukem 	const struct cindexrec	*cir2 = v_cir2;
43*2de962bdSlukem 	int i = cir1->cir_name.bv_len - cir2->cir_name.bv_len;
44*2de962bdSlukem 	if (i) return i;
45*2de962bdSlukem 	return strcasecmp( cir1->cir_name.bv_val, cir2->cir_name.bv_val );
46*2de962bdSlukem }
47*2de962bdSlukem 
48*2de962bdSlukem static int
49*2de962bdSlukem cr_index_name_cmp(
50*2de962bdSlukem     const void	*v_name,
51*2de962bdSlukem     const void	*v_cir )
52*2de962bdSlukem {
53*2de962bdSlukem 	const struct berval    *name = v_name;
54*2de962bdSlukem 	const struct cindexrec *cir  = v_cir;
55*2de962bdSlukem 	int i = name->bv_len - cir->cir_name.bv_len;
56*2de962bdSlukem 	if (i) return i;
57*2de962bdSlukem 	return strncasecmp( name->bv_val, cir->cir_name.bv_val, name->bv_len );
58*2de962bdSlukem }
59*2de962bdSlukem 
60*2de962bdSlukem ContentRule *
61*2de962bdSlukem cr_find( const char *crname )
62*2de962bdSlukem {
63*2de962bdSlukem 	struct berval bv;
64*2de962bdSlukem 
65*2de962bdSlukem 	bv.bv_val = (char *)crname;
66*2de962bdSlukem 	bv.bv_len = strlen( crname );
67*2de962bdSlukem 
68*2de962bdSlukem 	return( cr_bvfind( &bv ) );
69*2de962bdSlukem }
70*2de962bdSlukem 
71*2de962bdSlukem ContentRule *
72*2de962bdSlukem cr_bvfind( struct berval *crname )
73*2de962bdSlukem {
74*2de962bdSlukem 	struct cindexrec	*cir;
75*2de962bdSlukem 
76*2de962bdSlukem 	cir = avl_find( cr_index, crname, cr_index_name_cmp );
77*2de962bdSlukem 
78*2de962bdSlukem 	if ( cir != NULL ) {
79*2de962bdSlukem 		return( cir->cir_cr );
80*2de962bdSlukem 	}
81*2de962bdSlukem 
82*2de962bdSlukem 	return( NULL );
83*2de962bdSlukem }
84*2de962bdSlukem 
85*2de962bdSlukem static int
86*2de962bdSlukem cr_destroy_one( ContentRule *c )
87*2de962bdSlukem {
88*2de962bdSlukem 	assert( c != NULL );
89*2de962bdSlukem 
90*2de962bdSlukem 	if (c->scr_auxiliaries) ldap_memfree(c->scr_auxiliaries);
91*2de962bdSlukem 	if (c->scr_required) ldap_memfree(c->scr_required);
92*2de962bdSlukem 	if (c->scr_allowed) ldap_memfree(c->scr_allowed);
93*2de962bdSlukem 	if (c->scr_precluded) ldap_memfree(c->scr_precluded);
94*2de962bdSlukem 	ldap_contentrule_free((LDAPContentRule *)c);
95*2de962bdSlukem 
96*2de962bdSlukem 	return 0;
97*2de962bdSlukem }
98*2de962bdSlukem 
99*2de962bdSlukem void
100*2de962bdSlukem cr_destroy( void )
101*2de962bdSlukem {
102*2de962bdSlukem 	ContentRule *c;
103*2de962bdSlukem 
104*2de962bdSlukem 	avl_free(cr_index, ldap_memfree);
105*2de962bdSlukem 
106*2de962bdSlukem 	while( !LDAP_STAILQ_EMPTY(&cr_list) ) {
107*2de962bdSlukem 		c = LDAP_STAILQ_FIRST(&cr_list);
108*2de962bdSlukem 		LDAP_STAILQ_REMOVE_HEAD(&cr_list, scr_next);
109*2de962bdSlukem 
110*2de962bdSlukem 		cr_destroy_one( c );
111*2de962bdSlukem 	}
112*2de962bdSlukem }
113*2de962bdSlukem 
114*2de962bdSlukem static int
115*2de962bdSlukem cr_insert(
116*2de962bdSlukem     ContentRule		*scr,
117*2de962bdSlukem     const char		**err
118*2de962bdSlukem )
119*2de962bdSlukem {
120*2de962bdSlukem 	struct cindexrec	*cir;
121*2de962bdSlukem 	char			**names;
122*2de962bdSlukem 
123*2de962bdSlukem 	if ( scr->scr_oid ) {
124*2de962bdSlukem 		cir = (struct cindexrec *)
125*2de962bdSlukem 			ch_calloc( 1, sizeof(struct cindexrec) );
126*2de962bdSlukem 		cir->cir_name.bv_val = scr->scr_oid;
127*2de962bdSlukem 		cir->cir_name.bv_len = strlen( scr->scr_oid );
128*2de962bdSlukem 		cir->cir_cr = scr;
129*2de962bdSlukem 
130*2de962bdSlukem 		assert( cir->cir_name.bv_val != NULL );
131*2de962bdSlukem 		assert( cir->cir_cr != NULL );
132*2de962bdSlukem 
133*2de962bdSlukem 		if ( avl_insert( &cr_index, (caddr_t) cir,
134*2de962bdSlukem 		                 cr_index_cmp, avl_dup_error ) )
135*2de962bdSlukem 		{
136*2de962bdSlukem 			*err = scr->scr_oid;
137*2de962bdSlukem 			ldap_memfree(cir);
138*2de962bdSlukem 			return SLAP_SCHERR_CR_DUP;
139*2de962bdSlukem 		}
140*2de962bdSlukem 
141*2de962bdSlukem 		/* FIX: temporal consistency check */
142*2de962bdSlukem 		assert( cr_bvfind(&cir->cir_name) != NULL );
143*2de962bdSlukem 	}
144*2de962bdSlukem 
145*2de962bdSlukem 	if ( (names = scr->scr_names) ) {
146*2de962bdSlukem 		while ( *names ) {
147*2de962bdSlukem 			cir = (struct cindexrec *)
148*2de962bdSlukem 				ch_calloc( 1, sizeof(struct cindexrec) );
149*2de962bdSlukem 			cir->cir_name.bv_val = *names;
150*2de962bdSlukem 			cir->cir_name.bv_len = strlen( *names );
151*2de962bdSlukem 			cir->cir_cr = scr;
152*2de962bdSlukem 
153*2de962bdSlukem 			assert( cir->cir_name.bv_val != NULL );
154*2de962bdSlukem 			assert( cir->cir_cr != NULL );
155*2de962bdSlukem 
156*2de962bdSlukem 			if ( avl_insert( &cr_index, (caddr_t) cir,
157*2de962bdSlukem 			                 cr_index_cmp, avl_dup_error ) )
158*2de962bdSlukem 			{
159*2de962bdSlukem 				*err = *names;
160*2de962bdSlukem 				ldap_memfree(cir);
161*2de962bdSlukem 				return SLAP_SCHERR_CR_DUP;
162*2de962bdSlukem 			}
163*2de962bdSlukem 
164*2de962bdSlukem 			/* FIX: temporal consistency check */
165*2de962bdSlukem 			assert( cr_bvfind(&cir->cir_name) != NULL );
166*2de962bdSlukem 
167*2de962bdSlukem 			names++;
168*2de962bdSlukem 		}
169*2de962bdSlukem 	}
170*2de962bdSlukem 
171*2de962bdSlukem 	LDAP_STAILQ_INSERT_TAIL(&cr_list, scr, scr_next);
172*2de962bdSlukem 
173*2de962bdSlukem 	return 0;
174*2de962bdSlukem }
175*2de962bdSlukem 
176*2de962bdSlukem static int
177*2de962bdSlukem cr_add_auxiliaries(
178*2de962bdSlukem     ContentRule		*scr,
179*2de962bdSlukem 	int			*op,
180*2de962bdSlukem     const char		**err )
181*2de962bdSlukem {
182*2de962bdSlukem 	int naux;
183*2de962bdSlukem 
184*2de962bdSlukem 	if( scr->scr_oc_oids_aux == NULL ) return 0;
185*2de962bdSlukem 
186*2de962bdSlukem 	for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
187*2de962bdSlukem 		/* count them */ ;
188*2de962bdSlukem 	}
189*2de962bdSlukem 
190*2de962bdSlukem 	scr->scr_auxiliaries = ch_calloc( naux+1, sizeof(ObjectClass *));
191*2de962bdSlukem 
192*2de962bdSlukem 	for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
193*2de962bdSlukem 		ObjectClass *soc = scr->scr_auxiliaries[naux]
194*2de962bdSlukem 			= oc_find(scr->scr_oc_oids_aux[naux]);
195*2de962bdSlukem 		if ( !soc ) {
196*2de962bdSlukem 			*err = scr->scr_oc_oids_aux[naux];
197*2de962bdSlukem 			return SLAP_SCHERR_CLASS_NOT_FOUND;
198*2de962bdSlukem 		}
199*2de962bdSlukem 
200*2de962bdSlukem 		if( soc->soc_flags & SLAP_OC_OPERATIONAL &&
201*2de962bdSlukem 			soc != slap_schema.si_oc_extensibleObject )
202*2de962bdSlukem 		{
203*2de962bdSlukem 			(*op)++;
204*2de962bdSlukem 		}
205*2de962bdSlukem 
206*2de962bdSlukem 		if( soc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
207*2de962bdSlukem 			*err = scr->scr_oc_oids_aux[naux];
208*2de962bdSlukem 			return SLAP_SCHERR_CR_BAD_AUX;
209*2de962bdSlukem 		}
210*2de962bdSlukem 	}
211*2de962bdSlukem 
212*2de962bdSlukem 	scr->scr_auxiliaries[naux] = NULL;
213*2de962bdSlukem 	return 0;
214*2de962bdSlukem }
215*2de962bdSlukem 
216*2de962bdSlukem static int
217*2de962bdSlukem cr_create_required(
218*2de962bdSlukem     ContentRule		*scr,
219*2de962bdSlukem 	int			*op,
220*2de962bdSlukem     const char		**err )
221*2de962bdSlukem {
222*2de962bdSlukem     char		**attrs = scr->scr_at_oids_must;
223*2de962bdSlukem 	char		**attrs1;
224*2de962bdSlukem 	AttributeType	*sat;
225*2de962bdSlukem 
226*2de962bdSlukem 	if ( attrs ) {
227*2de962bdSlukem 		attrs1 = attrs;
228*2de962bdSlukem 		while ( *attrs1 ) {
229*2de962bdSlukem 			sat = at_find(*attrs1);
230*2de962bdSlukem 			if ( !sat ) {
231*2de962bdSlukem 				*err = *attrs1;
232*2de962bdSlukem 				return SLAP_SCHERR_ATTR_NOT_FOUND;
233*2de962bdSlukem 			}
234*2de962bdSlukem 
235*2de962bdSlukem 			if( is_at_operational( sat )) (*op)++;
236*2de962bdSlukem 
237*2de962bdSlukem 			if ( at_find_in_list(sat, scr->scr_required) < 0) {
238*2de962bdSlukem 				if ( at_append_to_list(sat, &scr->scr_required) ) {
239*2de962bdSlukem 					*err = *attrs1;
240*2de962bdSlukem 					return SLAP_SCHERR_OUTOFMEM;
241*2de962bdSlukem 				}
242*2de962bdSlukem 			} else {
243*2de962bdSlukem 				*err = *attrs1;
244*2de962bdSlukem 				return SLAP_SCHERR_CR_BAD_AT;
245*2de962bdSlukem 			}
246*2de962bdSlukem 			attrs1++;
247*2de962bdSlukem 		}
248*2de962bdSlukem 	}
249*2de962bdSlukem 	return 0;
250*2de962bdSlukem }
251*2de962bdSlukem 
252*2de962bdSlukem static int
253*2de962bdSlukem cr_create_allowed(
254*2de962bdSlukem     ContentRule		*scr,
255*2de962bdSlukem 	int			*op,
256*2de962bdSlukem     const char		**err )
257*2de962bdSlukem {
258*2de962bdSlukem     char		**attrs = scr->scr_at_oids_may;
259*2de962bdSlukem 	char		**attrs1;
260*2de962bdSlukem 	AttributeType	*sat;
261*2de962bdSlukem 
262*2de962bdSlukem 	if ( attrs ) {
263*2de962bdSlukem 		attrs1 = attrs;
264*2de962bdSlukem 		while ( *attrs1 ) {
265*2de962bdSlukem 			sat = at_find(*attrs1);
266*2de962bdSlukem 			if ( !sat ) {
267*2de962bdSlukem 				*err = *attrs1;
268*2de962bdSlukem 				return SLAP_SCHERR_ATTR_NOT_FOUND;
269*2de962bdSlukem 			}
270*2de962bdSlukem 
271*2de962bdSlukem 			if( is_at_operational( sat )) (*op)++;
272*2de962bdSlukem 
273*2de962bdSlukem 			if ( at_find_in_list(sat, scr->scr_required) < 0 &&
274*2de962bdSlukem 				at_find_in_list(sat, scr->scr_allowed) < 0 )
275*2de962bdSlukem 			{
276*2de962bdSlukem 				if ( at_append_to_list(sat, &scr->scr_allowed) ) {
277*2de962bdSlukem 					*err = *attrs1;
278*2de962bdSlukem 					return SLAP_SCHERR_OUTOFMEM;
279*2de962bdSlukem 				}
280*2de962bdSlukem 			} else {
281*2de962bdSlukem 				*err = *attrs1;
282*2de962bdSlukem 				return SLAP_SCHERR_CR_BAD_AT;
283*2de962bdSlukem 			}
284*2de962bdSlukem 			attrs1++;
285*2de962bdSlukem 		}
286*2de962bdSlukem 	}
287*2de962bdSlukem 	return 0;
288*2de962bdSlukem }
289*2de962bdSlukem 
290*2de962bdSlukem static int
291*2de962bdSlukem cr_create_precluded(
292*2de962bdSlukem     ContentRule		*scr,
293*2de962bdSlukem 	int			*op,
294*2de962bdSlukem     const char		**err )
295*2de962bdSlukem {
296*2de962bdSlukem     char		**attrs = scr->scr_at_oids_not;
297*2de962bdSlukem 	char		**attrs1;
298*2de962bdSlukem 	AttributeType	*sat;
299*2de962bdSlukem 
300*2de962bdSlukem 	if ( attrs ) {
301*2de962bdSlukem 		attrs1 = attrs;
302*2de962bdSlukem 		while ( *attrs1 ) {
303*2de962bdSlukem 			sat = at_find(*attrs1);
304*2de962bdSlukem 			if ( !sat ) {
305*2de962bdSlukem 				*err = *attrs1;
306*2de962bdSlukem 				return SLAP_SCHERR_ATTR_NOT_FOUND;
307*2de962bdSlukem 			}
308*2de962bdSlukem 
309*2de962bdSlukem 			if( is_at_operational( sat )) (*op)++;
310*2de962bdSlukem 
311*2de962bdSlukem 			/* FIXME: should also make sure attribute type is not
312*2de962bdSlukem 				a required attribute of the structural class or
313*2de962bdSlukem 				any auxiliary class */
314*2de962bdSlukem 			if ( at_find_in_list(sat, scr->scr_required) < 0 &&
315*2de962bdSlukem 				at_find_in_list(sat, scr->scr_allowed) < 0 &&
316*2de962bdSlukem 				at_find_in_list(sat, scr->scr_precluded) < 0 )
317*2de962bdSlukem 			{
318*2de962bdSlukem 				if ( at_append_to_list(sat, &scr->scr_precluded) ) {
319*2de962bdSlukem 					*err = *attrs1;
320*2de962bdSlukem 					return SLAP_SCHERR_OUTOFMEM;
321*2de962bdSlukem 				}
322*2de962bdSlukem 			} else {
323*2de962bdSlukem 				*err = *attrs1;
324*2de962bdSlukem 				return SLAP_SCHERR_CR_BAD_AT;
325*2de962bdSlukem 			}
326*2de962bdSlukem 			attrs1++;
327*2de962bdSlukem 		}
328*2de962bdSlukem 	}
329*2de962bdSlukem 	return 0;
330*2de962bdSlukem }
331*2de962bdSlukem 
332*2de962bdSlukem int
333*2de962bdSlukem cr_add(
334*2de962bdSlukem     LDAPContentRule	*cr,
335*2de962bdSlukem 	int user,
336*2de962bdSlukem 	ContentRule **rscr,
337*2de962bdSlukem     const char		**err
338*2de962bdSlukem )
339*2de962bdSlukem {
340*2de962bdSlukem 	ContentRule	*scr;
341*2de962bdSlukem 	int		code;
342*2de962bdSlukem 	int		op = 0;
343*2de962bdSlukem 	char	*oidm = NULL;
344*2de962bdSlukem 
345*2de962bdSlukem 	if ( cr->cr_names != NULL ) {
346*2de962bdSlukem 		int i;
347*2de962bdSlukem 
348*2de962bdSlukem 		for( i=0; cr->cr_names[i]; i++ ) {
349*2de962bdSlukem 			if( !slap_valid_descr( cr->cr_names[i] ) ) {
350*2de962bdSlukem 				return SLAP_SCHERR_BAD_DESCR;
351*2de962bdSlukem 			}
352*2de962bdSlukem 		}
353*2de962bdSlukem 	}
354*2de962bdSlukem 
355*2de962bdSlukem 	if ( !OID_LEADCHAR( cr->cr_oid[0] )) {
356*2de962bdSlukem 		/* Expand OID macros */
357*2de962bdSlukem 		char *oid = oidm_find( cr->cr_oid );
358*2de962bdSlukem 		if ( !oid ) {
359*2de962bdSlukem 			*err = cr->cr_oid;
360*2de962bdSlukem 			return SLAP_SCHERR_OIDM;
361*2de962bdSlukem 		}
362*2de962bdSlukem 		if ( oid != cr->cr_oid ) {
363*2de962bdSlukem 			oidm = cr->cr_oid;
364*2de962bdSlukem 			cr->cr_oid = oid;
365*2de962bdSlukem 		}
366*2de962bdSlukem 	}
367*2de962bdSlukem 
368*2de962bdSlukem 	scr = (ContentRule *) ch_calloc( 1, sizeof(ContentRule) );
369*2de962bdSlukem 	AC_MEMCPY( &scr->scr_crule, cr, sizeof(LDAPContentRule) );
370*2de962bdSlukem 
371*2de962bdSlukem 	scr->scr_oidmacro = oidm;
372*2de962bdSlukem 	scr->scr_sclass = oc_find(cr->cr_oid);
373*2de962bdSlukem 	if ( !scr->scr_sclass ) {
374*2de962bdSlukem 		*err = cr->cr_oid;
375*2de962bdSlukem 		code = SLAP_SCHERR_CLASS_NOT_FOUND;
376*2de962bdSlukem 		goto fail;
377*2de962bdSlukem 	}
378*2de962bdSlukem 
379*2de962bdSlukem 	/* check object class usage */
380*2de962bdSlukem 	if( scr->scr_sclass->soc_kind != LDAP_SCHEMA_STRUCTURAL )
381*2de962bdSlukem 	{
382*2de962bdSlukem 		*err = cr->cr_oid;
383*2de962bdSlukem 		code = SLAP_SCHERR_CR_BAD_STRUCT;
384*2de962bdSlukem 		goto fail;
385*2de962bdSlukem 	}
386*2de962bdSlukem 
387*2de962bdSlukem 	if( scr->scr_sclass->soc_flags & SLAP_OC_OPERATIONAL ) op++;
388*2de962bdSlukem 
389*2de962bdSlukem 	code = cr_add_auxiliaries( scr, &op, err );
390*2de962bdSlukem 	if ( code != 0 ) goto fail;
391*2de962bdSlukem 
392*2de962bdSlukem 	code = cr_create_required( scr, &op, err );
393*2de962bdSlukem 	if ( code != 0 ) goto fail;
394*2de962bdSlukem 
395*2de962bdSlukem 	code = cr_create_allowed( scr, &op, err );
396*2de962bdSlukem 	if ( code != 0 ) goto fail;
397*2de962bdSlukem 
398*2de962bdSlukem 	code = cr_create_precluded( scr, &op, err );
399*2de962bdSlukem 	if ( code != 0 ) goto fail;
400*2de962bdSlukem 
401*2de962bdSlukem 	if( user && op ) {
402*2de962bdSlukem 		code = SLAP_SCHERR_CR_BAD_AUX;
403*2de962bdSlukem 		goto fail;
404*2de962bdSlukem 	}
405*2de962bdSlukem 
406*2de962bdSlukem 	code = cr_insert(scr,err);
407*2de962bdSlukem 	if ( code == 0 && rscr )
408*2de962bdSlukem 		*rscr = scr;
409*2de962bdSlukem 	return code;
410*2de962bdSlukem fail:
411*2de962bdSlukem 	ch_free( scr );
412*2de962bdSlukem 	return code;
413*2de962bdSlukem }
414*2de962bdSlukem 
415*2de962bdSlukem void
416*2de962bdSlukem cr_unparse( BerVarray *res, ContentRule *start, ContentRule *end, int sys )
417*2de962bdSlukem {
418*2de962bdSlukem 	ContentRule *cr;
419*2de962bdSlukem 	int i, num;
420*2de962bdSlukem 	struct berval bv, *bva = NULL, idx;
421*2de962bdSlukem 	char ibuf[32];
422*2de962bdSlukem 
423*2de962bdSlukem 	if ( !start )
424*2de962bdSlukem 		start = LDAP_STAILQ_FIRST( &cr_list );
425*2de962bdSlukem 
426*2de962bdSlukem 	/* count the result size */
427*2de962bdSlukem 	i = 0;
428*2de962bdSlukem 	for ( cr=start; cr; cr=LDAP_STAILQ_NEXT(cr, scr_next)) {
429*2de962bdSlukem 		if ( sys && !(cr->scr_flags & SLAP_CR_HARDCODE)) continue;
430*2de962bdSlukem 		i++;
431*2de962bdSlukem 		if ( cr == end ) break;
432*2de962bdSlukem 	}
433*2de962bdSlukem 	if (!i) return;
434*2de962bdSlukem 
435*2de962bdSlukem 	num = i;
436*2de962bdSlukem 	bva = ch_malloc( (num+1) * sizeof(struct berval) );
437*2de962bdSlukem 	BER_BVZERO( bva );
438*2de962bdSlukem 	idx.bv_val = ibuf;
439*2de962bdSlukem 	if ( sys ) {
440*2de962bdSlukem 		idx.bv_len = 0;
441*2de962bdSlukem 		ibuf[0] = '\0';
442*2de962bdSlukem 	}
443*2de962bdSlukem 	i = 0;
444*2de962bdSlukem 	for ( cr=start; cr; cr=LDAP_STAILQ_NEXT(cr, scr_next)) {
445*2de962bdSlukem 		LDAPContentRule lcr, *lcrp;
446*2de962bdSlukem 		if ( sys && !(cr->scr_flags & SLAP_CR_HARDCODE)) continue;
447*2de962bdSlukem 		if ( cr->scr_oidmacro ) {
448*2de962bdSlukem 			lcr = cr->scr_crule;
449*2de962bdSlukem 			lcr.cr_oid = cr->scr_oidmacro;
450*2de962bdSlukem 			lcrp = &lcr;
451*2de962bdSlukem 		} else {
452*2de962bdSlukem 			lcrp = &cr->scr_crule;
453*2de962bdSlukem 		}
454*2de962bdSlukem 		if ( ldap_contentrule2bv( lcrp, &bv ) == NULL ) {
455*2de962bdSlukem 			ber_bvarray_free( bva );
456*2de962bdSlukem 		}
457*2de962bdSlukem 		if ( !sys ) {
458*2de962bdSlukem 			idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
459*2de962bdSlukem 		}
460*2de962bdSlukem 		bva[i].bv_len = idx.bv_len + bv.bv_len;
461*2de962bdSlukem 		bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
462*2de962bdSlukem 		strcpy( bva[i].bv_val, ibuf );
463*2de962bdSlukem 		strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
464*2de962bdSlukem 		i++;
465*2de962bdSlukem 		bva[i].bv_val = NULL;
466*2de962bdSlukem 		ldap_memfree( bv.bv_val );
467*2de962bdSlukem 		if ( cr == end ) break;
468*2de962bdSlukem 	}
469*2de962bdSlukem 	*res = bva;
470*2de962bdSlukem }
471*2de962bdSlukem 
472*2de962bdSlukem int
473*2de962bdSlukem cr_schema_info( Entry *e )
474*2de962bdSlukem {
475*2de962bdSlukem 	AttributeDescription *ad_ditContentRules
476*2de962bdSlukem 		= slap_schema.si_ad_ditContentRules;
477*2de962bdSlukem 	ContentRule	*cr;
478*2de962bdSlukem 
479*2de962bdSlukem 	struct berval	val;
480*2de962bdSlukem 	struct berval	nval;
481*2de962bdSlukem 
482*2de962bdSlukem 	LDAP_STAILQ_FOREACH(cr, &cr_list, scr_next) {
483*2de962bdSlukem 		if ( ldap_contentrule2bv( &cr->scr_crule, &val ) == NULL ) {
484*2de962bdSlukem 			return -1;
485*2de962bdSlukem 		}
486*2de962bdSlukem 
487*2de962bdSlukem #if 0
488*2de962bdSlukem 		if( cr->scr_flags & SLAP_CR_HIDE ) continue;
489*2de962bdSlukem #endif
490*2de962bdSlukem #if 0
491*2de962bdSlukem 		Debug( LDAP_DEBUG_TRACE, "Merging cr [%ld] %s\n",
492*2de962bdSlukem 	       (long) val.bv_len, val.bv_val, 0 );
493*2de962bdSlukem #endif
494*2de962bdSlukem 
495*2de962bdSlukem 		nval.bv_val = cr->scr_oid;
496*2de962bdSlukem 		nval.bv_len = strlen(cr->scr_oid);
497*2de962bdSlukem 
498*2de962bdSlukem 		if( attr_merge_one( e, ad_ditContentRules, &val, &nval ) )
499*2de962bdSlukem 		{
500*2de962bdSlukem 			return -1;
501*2de962bdSlukem 		}
502*2de962bdSlukem 		ldap_memfree( val.bv_val );
503*2de962bdSlukem 	}
504*2de962bdSlukem 	return 0;
505*2de962bdSlukem }
506