xref: /netbsd-src/external/bsd/openldap/dist/contrib/slapd-modules/allowed/allowed.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: allowed.c,v 1.3 2021/08/14 16:14:50 christos Exp $	*/
24e6df137Slukem 
34e6df137Slukem /* allowed.c - add allowed attributes based on ACL */
4d11b170bStron /* $OpenLDAP$ */
54e6df137Slukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
64e6df137Slukem  *
7*549b59edSchristos  * Copyright 2006-2021 The OpenLDAP Foundation.
84e6df137Slukem  * All rights reserved.
94e6df137Slukem  *
104e6df137Slukem  * Redistribution and use in source and binary forms, with or without
114e6df137Slukem  * modification, are permitted only as authorized by the OpenLDAP
124e6df137Slukem  * Public License.
134e6df137Slukem  *
144e6df137Slukem  * A copy of this license is available in the file LICENSE in the
154e6df137Slukem  * top-level directory of the distribution or, alternatively, at
164e6df137Slukem  * <http://www.OpenLDAP.org/license.html>.
174e6df137Slukem  */
184e6df137Slukem /* ACKNOWLEDGEMENTS:
194e6df137Slukem  * This work was initially developed by Pierangelo Masarati for inclusion in
204e6df137Slukem  * OpenLDAP Software.
214e6df137Slukem  */
224e6df137Slukem 
234e6df137Slukem /*
244e6df137Slukem  * Rationale: return in allowedAttributes the attributes required/allowed
254e6df137Slukem  * by the objectClasses that are currently present in an object; return
264e6df137Slukem  * in allowedAttributesEffective the subset of the above that can be written
274e6df137Slukem  * by the identity that performs the search.
284e6df137Slukem  *
294e6df137Slukem  * Caveats:
304e6df137Slukem  * - right now, the overlay assumes that all values of the objectClass
314e6df137Slukem  *   attribute will be returned in rs->sr_entry; this may not be true
32*549b59edSchristos  *   in general, but it usually is for back-mdb.  To generalize,
334e6df137Slukem  *   the search request should be analyzed, and if allowedAttributes or
344e6df137Slukem  *   allowedAttributesEffective are requested, add objectClass to the
354e6df137Slukem  *   requested attributes
364e6df137Slukem  * - it assumes that there is no difference between write-add and
374e6df137Slukem  *   write-delete
384e6df137Slukem  * - it assumes that access rules do not depend on the values of the
394e6df137Slukem  *   attributes or on the contents of the entry (attr/val, filter, ...)
404e6df137Slukem  *   allowedAttributes and allowedAttributesEffective cannot be used
414e6df137Slukem  *   in filters or in compare
424e6df137Slukem  */
434e6df137Slukem 
44376af7d7Schristos #include <sys/cdefs.h>
45*549b59edSchristos __RCSID("$NetBSD: allowed.c,v 1.3 2021/08/14 16:14:50 christos Exp $");
46376af7d7Schristos 
474e6df137Slukem #include "portable.h"
484e6df137Slukem 
494e6df137Slukem /* define SLAPD_OVER_ALLOWED=2 to build as run-time loadable module */
504e6df137Slukem #ifdef SLAPD_OVER_ALLOWED
514e6df137Slukem 
524e6df137Slukem #include "slap.h"
534e6df137Slukem 
544e6df137Slukem /*
55d11b170bStron  * NOTE: part of the schema definition reported below is taken
56d11b170bStron  * from Microsoft schema definitions (OID, NAME, SYNTAX);
574e6df137Slukem  *
58d11b170bStron  * EQUALITY is taken from
594e6df137Slukem  * <http://www.redhat.com/archives/fedora-directory-devel/2006-August/msg00007.html>
60d11b170bStron  * (posted by Andrew Bartlett)
614e6df137Slukem  *
62d11b170bStron  * The rest is guessed.  Specifically
63d11b170bStron  *
64d11b170bStron  * DESC briefly describes the purpose
65d11b170bStron  *
66d11b170bStron  * NO-USER-MODIFICATION is added to make attributes operational
67d11b170bStron  *
68d11b170bStron  * USAGE is set to "dSAOperation" as per ITS#7493,
69d11b170bStron  * to prevent replication, since this information
70d11b170bStron  * is generated (based on ACL and identity of request)
71d11b170bStron  * and not stored.
724e6df137Slukem  */
734e6df137Slukem 
744e6df137Slukem #define AA_SCHEMA_AT "1.2.840.113556.1.4"
754e6df137Slukem 
764e6df137Slukem static AttributeDescription
774e6df137Slukem 		*ad_allowedChildClasses,
784e6df137Slukem 		*ad_allowedChildClassesEffective,
794e6df137Slukem 		*ad_allowedAttributes,
804e6df137Slukem 		*ad_allowedAttributesEffective;
814e6df137Slukem 
824e6df137Slukem static struct {
834e6df137Slukem 	char *at;
844e6df137Slukem 	AttributeDescription **ad;
854e6df137Slukem } aa_attrs[] = {
864e6df137Slukem 	{ "( " AA_SCHEMA_AT ".911 "
874e6df137Slukem 		"NAME 'allowedChildClasses' "
884e6df137Slukem 		"EQUALITY objectIdentifierMatch "
894e6df137Slukem 		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
904e6df137Slukem 		/* added by me :) */
914e6df137Slukem 		"DESC 'Child classes allowed for a given object' "
924e6df137Slukem 		"NO-USER-MODIFICATION "
93d11b170bStron 		"USAGE dSAOperation )", &ad_allowedChildClasses },
944e6df137Slukem 	{ "( " AA_SCHEMA_AT ".912 "
954e6df137Slukem 		"NAME 'allowedChildClassesEffective' "
964e6df137Slukem 		"EQUALITY objectIdentifierMatch "
974e6df137Slukem 		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
984e6df137Slukem 		/* added by me :) */
994e6df137Slukem 		"DESC 'Child classes allowed for a given object according to ACLs' "
1004e6df137Slukem 		"NO-USER-MODIFICATION "
101d11b170bStron 		"USAGE dSAOperation )", &ad_allowedChildClassesEffective },
1024e6df137Slukem 	{ "( " AA_SCHEMA_AT ".913 "
1034e6df137Slukem 		"NAME 'allowedAttributes' "
1044e6df137Slukem 		"EQUALITY objectIdentifierMatch "
1054e6df137Slukem 		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
1064e6df137Slukem 		/* added by me :) */
1074e6df137Slukem 		"DESC 'Attributes allowed for a given object' "
1084e6df137Slukem 		"NO-USER-MODIFICATION "
109d11b170bStron 		"USAGE dSAOperation )", &ad_allowedAttributes },
1104e6df137Slukem 	{ "( " AA_SCHEMA_AT ".914 "
1114e6df137Slukem 		"NAME 'allowedAttributesEffective' "
1124e6df137Slukem 		"EQUALITY objectIdentifierMatch "
1134e6df137Slukem 		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
1144e6df137Slukem 		/* added by me :) */
1154e6df137Slukem 		"DESC 'Attributes allowed for a given object according to ACLs' "
1164e6df137Slukem 		"NO-USER-MODIFICATION "
117d11b170bStron 		"USAGE dSAOperation )", &ad_allowedAttributesEffective },
1184e6df137Slukem 
1194e6df137Slukem 	/* TODO: add objectClass stuff? */
1204e6df137Slukem 
1214e6df137Slukem 	{ NULL, NULL }
1224e6df137Slukem };
1234e6df137Slukem 
1244e6df137Slukem static int
aa_add_at(AttributeType * at,AttributeType *** atpp)1254e6df137Slukem aa_add_at( AttributeType *at, AttributeType ***atpp )
1264e6df137Slukem {
1274e6df137Slukem 	int		i = 0;
1284e6df137Slukem 
1294e6df137Slukem 	if ( *atpp ) {
1304e6df137Slukem 		for ( i = 0; (*atpp)[ i ] != NULL; i++ ) {
1314e6df137Slukem 			if ( (*atpp)[ i ] == at ) {
1324e6df137Slukem 				break;
1334e6df137Slukem 			}
1344e6df137Slukem 		}
1354e6df137Slukem 
1364e6df137Slukem 		if ( (*atpp)[ i ] != NULL ) {
1374e6df137Slukem 			return 0;
1384e6df137Slukem 		}
1394e6df137Slukem 	}
1404e6df137Slukem 
1414e6df137Slukem 	*atpp = ch_realloc( *atpp, sizeof( AttributeType * ) * ( i + 2 ) );
1424e6df137Slukem 	(*atpp)[ i ] = at;
1434e6df137Slukem 	(*atpp)[ i + 1 ] = NULL;
1444e6df137Slukem 
1454e6df137Slukem 	return 0;
1464e6df137Slukem }
1474e6df137Slukem 
1484e6df137Slukem static int
aa_add_oc(ObjectClass * oc,ObjectClass *** ocpp,AttributeType *** atpp)1494e6df137Slukem aa_add_oc( ObjectClass *oc, ObjectClass ***ocpp, AttributeType ***atpp )
1504e6df137Slukem {
1514e6df137Slukem 	int		i = 0;
1524e6df137Slukem 
1534e6df137Slukem 	if ( *ocpp ) {
1544e6df137Slukem 		for ( ; (*ocpp)[ i ] != NULL; i++ ) {
1554e6df137Slukem 			if ( (*ocpp)[ i ] == oc ) {
1564e6df137Slukem 				break;
1574e6df137Slukem 			}
1584e6df137Slukem 		}
1594e6df137Slukem 
1604e6df137Slukem 		if ( (*ocpp)[ i ] != NULL ) {
1614e6df137Slukem 			return 0;
1624e6df137Slukem 		}
1634e6df137Slukem 	}
1644e6df137Slukem 
1654e6df137Slukem 	*ocpp = ch_realloc( *ocpp, sizeof( ObjectClass * ) * ( i + 2 ) );
1664e6df137Slukem 	(*ocpp)[ i ] = oc;
1674e6df137Slukem 	(*ocpp)[ i + 1 ] = NULL;
1684e6df137Slukem 
1694e6df137Slukem 	if ( oc->soc_required ) {
1704e6df137Slukem 		int		i;
1714e6df137Slukem 
1724e6df137Slukem 		for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) {
1734e6df137Slukem 			aa_add_at( oc->soc_required[ i ], atpp );
1744e6df137Slukem 		}
1754e6df137Slukem 	}
1764e6df137Slukem 
1774e6df137Slukem 	if ( oc->soc_allowed ) {
1784e6df137Slukem 		int		i;
1794e6df137Slukem 
1804e6df137Slukem 		for ( i = 0; oc->soc_allowed[ i ] != NULL; i++ ) {
1814e6df137Slukem 			aa_add_at( oc->soc_allowed[ i ], atpp );
1824e6df137Slukem 		}
1834e6df137Slukem 	}
1844e6df137Slukem 
1854e6df137Slukem 	return 0;
1864e6df137Slukem }
1874e6df137Slukem 
1884e6df137Slukem static int
aa_operational(Operation * op,SlapReply * rs)1894e6df137Slukem aa_operational( Operation *op, SlapReply *rs )
1904e6df137Slukem {
1914e6df137Slukem 	Attribute		*a, **ap;
1924e6df137Slukem 	AccessControlState	acl_state = ACL_STATE_INIT;
1934e6df137Slukem 	struct berval		*v;
1944e6df137Slukem 	AttributeType		**atp = NULL;
1954e6df137Slukem 	ObjectClass		**ocp = NULL;
1964e6df137Slukem 
1974e6df137Slukem #define	GOT_NONE	(0x0U)
1984e6df137Slukem #define	GOT_C		(0x1U)
1994e6df137Slukem #define	GOT_CE		(0x2U)
2004e6df137Slukem #define	GOT_A		(0x4U)
2014e6df137Slukem #define	GOT_AE		(0x8U)
2024e6df137Slukem #define	GOT_ALL		(GOT_C|GOT_CE|GOT_A|GOT_AE)
2034e6df137Slukem 	int		got = GOT_NONE;
2044e6df137Slukem 
2054e6df137Slukem 	/* only add if requested */
2064e6df137Slukem 	if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) {
2074e6df137Slukem 		got = GOT_ALL;
2084e6df137Slukem 
2094e6df137Slukem 	} else {
2104e6df137Slukem 		if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) {
2114e6df137Slukem 			got |= GOT_C;
2124e6df137Slukem 		}
2134e6df137Slukem 
2144e6df137Slukem 		if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) {
2154e6df137Slukem 			got |= GOT_CE;
2164e6df137Slukem 		}
2174e6df137Slukem 
2184e6df137Slukem 		if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) {
2194e6df137Slukem 			got |= GOT_A;
2204e6df137Slukem 		}
2214e6df137Slukem 
2224e6df137Slukem 		if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) {
2234e6df137Slukem 			got |= GOT_AE;
2244e6df137Slukem 		}
2254e6df137Slukem 	}
2264e6df137Slukem 
2274e6df137Slukem 	if ( got == GOT_NONE ) {
2284e6df137Slukem 		return SLAP_CB_CONTINUE;
2294e6df137Slukem 	}
2304e6df137Slukem 
2314e6df137Slukem 	/* shouldn't be called without an entry; please check */
2324e6df137Slukem 	assert( rs->sr_entry != NULL );
2334e6df137Slukem 
234ef2f90d3Sadam 	for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next )
235ef2f90d3Sadam 		/* go to last */ ;
236ef2f90d3Sadam 
2374e6df137Slukem 	/* see caveats; this is not guaranteed for all backends */
2384e6df137Slukem 	a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass );
2394e6df137Slukem 	if ( a == NULL ) {
240ef2f90d3Sadam 		goto do_oc;
2414e6df137Slukem 	}
2424e6df137Slukem 
2434e6df137Slukem 	/* if client has no access to objectClass attribute; don't compute */
2444e6df137Slukem 	if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass,
2454e6df137Slukem 				NULL, ACL_READ, &acl_state ) )
2464e6df137Slukem 	{
2474e6df137Slukem 		return SLAP_CB_CONTINUE;
2484e6df137Slukem 	}
2494e6df137Slukem 
2504e6df137Slukem 	for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) {
2514e6df137Slukem 		ObjectClass	*oc = oc_bvfind( v );
2524e6df137Slukem 
2534e6df137Slukem 		assert( oc != NULL );
2544e6df137Slukem 
2554e6df137Slukem 		/* if client has no access to specific value, don't compute */
2564e6df137Slukem 		if ( !access_allowed( op, rs->sr_entry,
2574e6df137Slukem 			slap_schema.si_ad_objectClass,
2584e6df137Slukem 			&oc->soc_cname, ACL_READ, &acl_state ) )
2594e6df137Slukem 		{
2604e6df137Slukem 			continue;
2614e6df137Slukem 		}
2624e6df137Slukem 
2634e6df137Slukem 		aa_add_oc( oc, &ocp, &atp );
2644e6df137Slukem 
2654e6df137Slukem 		if ( oc->soc_sups ) {
266ef2f90d3Sadam 			int i;
267ef2f90d3Sadam 
2684e6df137Slukem 			for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) {
2694e6df137Slukem 				aa_add_oc( oc->soc_sups[ i ], &ocp, &atp );
2704e6df137Slukem 			}
2714e6df137Slukem 		}
2724e6df137Slukem 	}
2734e6df137Slukem 
274ef2f90d3Sadam 	ch_free( ocp );
275ef2f90d3Sadam 
2764e6df137Slukem 	if ( atp != NULL ) {
277ef2f90d3Sadam 		BerVarray	bv_allowed = NULL,
278ef2f90d3Sadam 				bv_effective = NULL;
279ef2f90d3Sadam 		int		i, ja = 0, je = 0;
280ef2f90d3Sadam 
2814e6df137Slukem 		for ( i = 0; atp[ i ] != NULL; i++ )
2824e6df137Slukem 			/* just count */ ;
2834e6df137Slukem 
2844e6df137Slukem 		if ( got & GOT_A ) {
285*549b59edSchristos 			bv_allowed = ch_calloc( i + 1,  sizeof( struct berval ) );
2864e6df137Slukem 		}
2874e6df137Slukem 		if ( got & GOT_AE ) {
288*549b59edSchristos 			bv_effective = ch_calloc( i + 1, sizeof( struct berval ) );
2894e6df137Slukem 		}
2904e6df137Slukem 
2914e6df137Slukem 		for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) {
2924e6df137Slukem 			if ( got & GOT_A ) {
2934e6df137Slukem 				ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname );
2944e6df137Slukem 				ja++;
2954e6df137Slukem 			}
2964e6df137Slukem 
2974e6df137Slukem 			if ( got & GOT_AE ) {
2984e6df137Slukem 				AttributeDescription	*ad = NULL;
2994e6df137Slukem 				const char		*text = NULL;
3004e6df137Slukem 
3014e6df137Slukem 				if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) {
3024e6df137Slukem 					/* log? */
3034e6df137Slukem 					continue;
3044e6df137Slukem 				}
3054e6df137Slukem 
3064e6df137Slukem 				if ( access_allowed( op, rs->sr_entry,
3074e6df137Slukem 					ad, NULL, ACL_WRITE, NULL ) )
3084e6df137Slukem 				{
3094e6df137Slukem 					ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname );
3104e6df137Slukem 					je++;
3114e6df137Slukem 				}
3124e6df137Slukem 			}
3134e6df137Slukem 		}
3144e6df137Slukem 
315ef2f90d3Sadam 		ch_free( atp );
3164e6df137Slukem 
3174e6df137Slukem 		if ( ( got & GOT_A ) && ja > 0 ) {
3184e6df137Slukem 			*ap = attr_alloc( ad_allowedAttributes );
3194e6df137Slukem 			(*ap)->a_vals = bv_allowed;
3204e6df137Slukem 			(*ap)->a_nvals = bv_allowed;
3214e6df137Slukem 			(*ap)->a_numvals = ja;
3224e6df137Slukem 			ap = &(*ap)->a_next;
3234e6df137Slukem 		}
3244e6df137Slukem 
3254e6df137Slukem 		if ( ( got & GOT_AE ) && je > 0 ) {
3264e6df137Slukem 			*ap = attr_alloc( ad_allowedAttributesEffective );
3274e6df137Slukem 			(*ap)->a_vals = bv_effective;
3284e6df137Slukem 			(*ap)->a_nvals = bv_effective;
3294e6df137Slukem 			(*ap)->a_numvals = je;
3304e6df137Slukem 			ap = &(*ap)->a_next;
3314e6df137Slukem 		}
3324e6df137Slukem 
3334e6df137Slukem 		*ap = NULL;
3344e6df137Slukem 	}
3354e6df137Slukem 
336ef2f90d3Sadam do_oc:;
337ef2f90d3Sadam 	if ( ( got & GOT_C ) || ( got & GOT_CE ) ) {
338ef2f90d3Sadam 		BerVarray	bv_allowed = NULL,
339ef2f90d3Sadam 				bv_effective = NULL;
340ef2f90d3Sadam 		int		i, ja = 0, je = 0;
341ef2f90d3Sadam 
342ef2f90d3Sadam 		ObjectClass	*oc;
343ef2f90d3Sadam 
344*549b59edSchristos 		for ( i = 0, oc_start( &oc ); oc != NULL; oc_next( &oc ) ) {
345ef2f90d3Sadam 			/* we can only add AUXILIARY objectClasses */
346ef2f90d3Sadam 			if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
347ef2f90d3Sadam 				continue;
348ef2f90d3Sadam 			}
349ef2f90d3Sadam 
350ef2f90d3Sadam 			i++;
351ef2f90d3Sadam 		}
352ef2f90d3Sadam 
353ef2f90d3Sadam 		if ( got & GOT_C ) {
354*549b59edSchristos 			bv_allowed = ch_calloc( i + 1,  sizeof( struct berval ) );
355ef2f90d3Sadam 		}
356ef2f90d3Sadam 		if ( got & GOT_CE ) {
357*549b59edSchristos 			bv_effective = ch_calloc( i + 1, sizeof( struct berval ) );
358ef2f90d3Sadam 		}
359ef2f90d3Sadam 
360ef2f90d3Sadam 		for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) {
361ef2f90d3Sadam 			/* we can only add AUXILIARY objectClasses */
362ef2f90d3Sadam 			if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
363ef2f90d3Sadam 				continue;
364ef2f90d3Sadam 			}
365ef2f90d3Sadam 
366ef2f90d3Sadam 			if ( got & GOT_C ) {
367ef2f90d3Sadam 				ber_dupbv( &bv_allowed[ ja ], &oc->soc_cname );
368ef2f90d3Sadam 				ja++;
369ef2f90d3Sadam 			}
370ef2f90d3Sadam 
371ef2f90d3Sadam 			if ( got & GOT_CE ) {
372ef2f90d3Sadam 				if ( !access_allowed( op, rs->sr_entry,
373ef2f90d3Sadam 					slap_schema.si_ad_objectClass,
374ef2f90d3Sadam 					&oc->soc_cname, ACL_WRITE, NULL ) )
375ef2f90d3Sadam 				{
376ef2f90d3Sadam 					goto done_ce;
377ef2f90d3Sadam 				}
378ef2f90d3Sadam 
379ef2f90d3Sadam 				if ( oc->soc_required ) {
380ef2f90d3Sadam 					for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) {
381ef2f90d3Sadam 						AttributeDescription	*ad = NULL;
382ef2f90d3Sadam 						const char		*text = NULL;
383ef2f90d3Sadam 
384ef2f90d3Sadam 						if ( slap_bv2ad( &oc->soc_required[ i ]->sat_cname, &ad, &text ) ) {
385ef2f90d3Sadam 							/* log? */
386ef2f90d3Sadam 							continue;
387ef2f90d3Sadam 						}
388ef2f90d3Sadam 
389ef2f90d3Sadam 						if ( !access_allowed( op, rs->sr_entry,
390ef2f90d3Sadam 							ad, NULL, ACL_WRITE, NULL ) )
391ef2f90d3Sadam 						{
392ef2f90d3Sadam 							goto done_ce;
393ef2f90d3Sadam 						}
394ef2f90d3Sadam 					}
395ef2f90d3Sadam 				}
396ef2f90d3Sadam 
397ef2f90d3Sadam 				ber_dupbv( &bv_effective[ je ], &oc->soc_cname );
398ef2f90d3Sadam 				je++;
399ef2f90d3Sadam 			}
400ef2f90d3Sadam done_ce:;
401ef2f90d3Sadam 		}
402ef2f90d3Sadam 
403ef2f90d3Sadam 		if ( ( got & GOT_C ) && ja > 0 ) {
404ef2f90d3Sadam 			*ap = attr_alloc( ad_allowedChildClasses );
405ef2f90d3Sadam 			(*ap)->a_vals = bv_allowed;
406ef2f90d3Sadam 			(*ap)->a_nvals = bv_allowed;
407ef2f90d3Sadam 			(*ap)->a_numvals = ja;
408ef2f90d3Sadam 			ap = &(*ap)->a_next;
409ef2f90d3Sadam 		}
410ef2f90d3Sadam 
411ef2f90d3Sadam 		if ( ( got & GOT_CE ) && je > 0 ) {
412ef2f90d3Sadam 			*ap = attr_alloc( ad_allowedChildClassesEffective );
413ef2f90d3Sadam 			(*ap)->a_vals = bv_effective;
414ef2f90d3Sadam 			(*ap)->a_nvals = bv_effective;
415ef2f90d3Sadam 			(*ap)->a_numvals = je;
416ef2f90d3Sadam 			ap = &(*ap)->a_next;
417ef2f90d3Sadam 		}
418ef2f90d3Sadam 
419ef2f90d3Sadam 		*ap = NULL;
420ef2f90d3Sadam 	}
4214e6df137Slukem 
4224e6df137Slukem 	return SLAP_CB_CONTINUE;
4234e6df137Slukem }
4244e6df137Slukem 
4254e6df137Slukem static slap_overinst aa;
4264e6df137Slukem 
4274e6df137Slukem #if LDAP_VENDOR_VERSION_MINOR != X && LDAP_VENDOR_VERSION_MINOR <= 3
4284e6df137Slukem /* backport register_at() from HEAD, to allow building with OL <= 2.3 */
4294e6df137Slukem static int
register_at(char * def,AttributeDescription ** rad,int dupok)4304e6df137Slukem register_at( char *def, AttributeDescription **rad, int dupok )
4314e6df137Slukem {
4324e6df137Slukem 	LDAPAttributeType *at;
4334e6df137Slukem 	int code, freeit = 0;
4344e6df137Slukem 	const char *err;
4354e6df137Slukem 	AttributeDescription *ad = NULL;
4364e6df137Slukem 
4374e6df137Slukem 	at = ldap_str2attributetype( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
4384e6df137Slukem 	if ( !at ) {
4394e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
4404e6df137Slukem 			"register_at: AttributeType \"%s\": %s, %s\n",
4414e6df137Slukem 				def, ldap_scherr2str(code), err );
4424e6df137Slukem 		return code;
4434e6df137Slukem 	}
4444e6df137Slukem 
4454e6df137Slukem 	code = at_add( at, 0, NULL, &err );
4464e6df137Slukem 	if ( code ) {
4474e6df137Slukem 		if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) {
4484e6df137Slukem 			freeit = 1;
4494e6df137Slukem 
4504e6df137Slukem 		} else {
4514e6df137Slukem 			ldap_attributetype_free( at );
4524e6df137Slukem 			Debug( LDAP_DEBUG_ANY,
4534e6df137Slukem 				"register_at: AttributeType \"%s\": %s, %s\n",
4544e6df137Slukem 				def, scherr2str(code), err );
4554e6df137Slukem 			return code;
4564e6df137Slukem 		}
4574e6df137Slukem 	}
4584e6df137Slukem 	code = slap_str2ad( at->at_names[0], &ad, &err );
4594e6df137Slukem 	if ( freeit || code ) {
4604e6df137Slukem 		ldap_attributetype_free( at );
4614e6df137Slukem 	} else {
4624e6df137Slukem 		ldap_memfree( at );
4634e6df137Slukem 	}
4644e6df137Slukem 	if ( code ) {
4654e6df137Slukem 		Debug( LDAP_DEBUG_ANY, "register_at: AttributeType \"%s\": %s\n",
466*549b59edSchristos 			def, err );
4674e6df137Slukem 	}
4684e6df137Slukem 	if ( rad ) *rad = ad;
4694e6df137Slukem 	return code;
4704e6df137Slukem }
4714e6df137Slukem #endif
4724e6df137Slukem 
4734e6df137Slukem #if SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC
4744e6df137Slukem static
4754e6df137Slukem #endif /* SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC */
4764e6df137Slukem int
aa_initialize(void)4774e6df137Slukem aa_initialize( void )
4784e6df137Slukem {
4794e6df137Slukem 	int i;
4804e6df137Slukem 
4814e6df137Slukem 	aa.on_bi.bi_type = "allowed";
4824e6df137Slukem 
483*549b59edSchristos 	aa.on_bi.bi_flags = SLAPO_BFLAG_SINGLE;
4844e6df137Slukem 	aa.on_bi.bi_operational = aa_operational;
4854e6df137Slukem 
4864e6df137Slukem 	/* aa schema integration */
4874e6df137Slukem 	for ( i = 0; aa_attrs[i].at; i++ ) {
4884e6df137Slukem 		int code;
4894e6df137Slukem 
4904e6df137Slukem 		code = register_at( aa_attrs[i].at, aa_attrs[i].ad, 0 );
4914e6df137Slukem 		if ( code ) {
4924e6df137Slukem 			Debug( LDAP_DEBUG_ANY,
493*549b59edSchristos 				"aa_initialize: register_at failed\n" );
4944e6df137Slukem 			return -1;
4954e6df137Slukem 		}
4964e6df137Slukem 	}
4974e6df137Slukem 
4984e6df137Slukem 	return overlay_register( &aa );
4994e6df137Slukem }
5004e6df137Slukem 
5014e6df137Slukem #if SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC
5024e6df137Slukem int
init_module(int argc,char * argv[])5034e6df137Slukem init_module( int argc, char *argv[] )
5044e6df137Slukem {
5054e6df137Slukem 	return aa_initialize();
5064e6df137Slukem }
5074e6df137Slukem #endif /* SLAPD_OVER_ALLOWED == SLAPD_MOD_DYNAMIC */
5084e6df137Slukem 
5094e6df137Slukem #endif /* SLAPD_OVER_ALLOWED */
510