Home | History | Annotate | Line # | Download | only in slapd
schema_prep.c revision 1.1.1.5
      1 /*	$NetBSD: schema_prep.c,v 1.1.1.5 2014/05/28 09:58:47 tron Exp $	*/
      2 
      3 /* schema_prep.c - load builtin schema */
      4 /* $OpenLDAP$ */
      5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  *
      7  * Copyright 1998-2014 The OpenLDAP Foundation.
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted only as authorized by the OpenLDAP
     12  * Public License.
     13  *
     14  * A copy of this license is available in the file LICENSE in the
     15  * top-level directory of the distribution or, alternatively, at
     16  * <http://www.OpenLDAP.org/license.html>.
     17  */
     18 
     19 #include "portable.h"
     20 
     21 #include <stdio.h>
     22 
     23 #include <ac/ctype.h>
     24 #include <ac/string.h>
     25 #include <ac/socket.h>
     26 
     27 #include "slap.h"
     28 
     29 #define OCDEBUG 0
     30 
     31 int schema_init_done = 0;
     32 
     33 struct slap_internal_schema slap_schema;
     34 
     35 static int
     36 oidValidate(
     37 	Syntax *syntax,
     38 	struct berval *in )
     39 {
     40 	struct berval val = *in;
     41 
     42 	if( val.bv_len == 0 ) {
     43 		/* disallow empty strings */
     44 		return LDAP_INVALID_SYNTAX;
     45 	}
     46 
     47 	if( DESC_LEADCHAR( val.bv_val[0] ) ) {
     48 		val.bv_val++;
     49 		val.bv_len--;
     50 		if ( val.bv_len == 0 ) return LDAP_SUCCESS;
     51 
     52 		while( DESC_CHAR( val.bv_val[0] ) ) {
     53 			val.bv_val++;
     54 			val.bv_len--;
     55 
     56 			if ( val.bv_len == 0 ) return LDAP_SUCCESS;
     57 		}
     58 
     59 	} else {
     60 		int sep = 0;
     61 		while( OID_LEADCHAR( val.bv_val[0] ) ) {
     62 			val.bv_val++;
     63 			val.bv_len--;
     64 
     65 			if ( val.bv_val[-1] != '0' ) {
     66 				while ( OID_LEADCHAR( val.bv_val[0] )) {
     67 					val.bv_val++;
     68 					val.bv_len--;
     69 				}
     70 			}
     71 
     72 			if( val.bv_len == 0 ) {
     73 				if( sep == 0 ) break;
     74 				return LDAP_SUCCESS;
     75 			}
     76 
     77 			if( !OID_SEPARATOR( val.bv_val[0] )) break;
     78 
     79 			sep++;
     80 			val.bv_val++;
     81 			val.bv_len--;
     82 		}
     83 	}
     84 
     85 	return LDAP_INVALID_SYNTAX;
     86 }
     87 
     88 
     89 static int objectClassPretty(
     90 	Syntax *syntax,
     91 	struct berval *in,
     92 	struct berval *out,
     93 	void *ctx )
     94 {
     95 	ObjectClass *oc;
     96 
     97 	if( oidValidate( NULL, in )) return LDAP_INVALID_SYNTAX;
     98 
     99 	oc = oc_bvfind( in );
    100 	if( oc == NULL ) return LDAP_INVALID_SYNTAX;
    101 
    102 	ber_dupbv_x( out, &oc->soc_cname, ctx );
    103 	return LDAP_SUCCESS;
    104 }
    105 
    106 static int
    107 attributeTypeMatch(
    108 	int *matchp,
    109 	slap_mask_t flags,
    110 	Syntax *syntax,
    111 	MatchingRule *mr,
    112 	struct berval *value,
    113 	void *assertedValue )
    114 {
    115 	struct berval *a = (struct berval *) assertedValue;
    116 	AttributeType *at = at_bvfind( value );
    117 	AttributeType *asserted = at_bvfind( a );
    118 
    119 	if( asserted == NULL ) {
    120 		if( OID_LEADCHAR( *a->bv_val ) ) {
    121 			/* OID form, return FALSE */
    122 			*matchp = 1;
    123 			return LDAP_SUCCESS;
    124 		}
    125 
    126 		/* desc form, return undefined */
    127 		return LDAP_INVALID_SYNTAX;
    128 	}
    129 
    130 	if ( at == NULL ) {
    131 		/* unrecognized stored value */
    132 		return LDAP_INVALID_SYNTAX;
    133 	}
    134 
    135 	*matchp = ( asserted != at );
    136 	return LDAP_SUCCESS;
    137 }
    138 
    139 static int
    140 matchingRuleMatch(
    141 	int *matchp,
    142 	slap_mask_t flags,
    143 	Syntax *syntax,
    144 	MatchingRule *mr,
    145 	struct berval *value,
    146 	void *assertedValue )
    147 {
    148 	struct berval *a = (struct berval *) assertedValue;
    149 	MatchingRule *mrv = mr_bvfind( value );
    150 	MatchingRule *asserted = mr_bvfind( a );
    151 
    152 	if( asserted == NULL ) {
    153 		if( OID_LEADCHAR( *a->bv_val ) ) {
    154 			/* OID form, return FALSE */
    155 			*matchp = 1;
    156 			return LDAP_SUCCESS;
    157 		}
    158 
    159 		/* desc form, return undefined */
    160 		return LDAP_INVALID_SYNTAX;
    161 	}
    162 
    163 	if ( mrv == NULL ) {
    164 		/* unrecognized stored value */
    165 		return LDAP_INVALID_SYNTAX;
    166 	}
    167 
    168 	*matchp = ( asserted != mrv );
    169 	return LDAP_SUCCESS;
    170 }
    171 
    172 static int
    173 objectClassMatch(
    174 	int *matchp,
    175 	slap_mask_t flags,
    176 	Syntax *syntax,
    177 	MatchingRule *mr,
    178 	struct berval *value,
    179 	void *assertedValue )
    180 {
    181 	struct berval *a = (struct berval *) assertedValue;
    182 	ObjectClass *oc = oc_bvfind( value );
    183 	ObjectClass *asserted = oc_bvfind( a );
    184 
    185 	if( asserted == NULL ) {
    186 		if( OID_LEADCHAR( *a->bv_val ) ) {
    187 			/* OID form, return FALSE */
    188 			*matchp = 1;
    189 			return LDAP_SUCCESS;
    190 		}
    191 
    192 		/* desc form, return undefined */
    193 		return LDAP_INVALID_SYNTAX;
    194 	}
    195 
    196 	if ( oc == NULL ) {
    197 		/* unrecognized stored value */
    198 		return LDAP_INVALID_SYNTAX;
    199 	}
    200 
    201 	*matchp = ( asserted != oc );
    202 	return LDAP_SUCCESS;
    203 }
    204 
    205 static int
    206 objectSubClassMatch(
    207 	int *matchp,
    208 	slap_mask_t flags,
    209 	Syntax *syntax,
    210 	MatchingRule *mr,
    211 	struct berval *value,
    212 	void *assertedValue )
    213 {
    214 	struct berval *a = (struct berval *) assertedValue;
    215 	ObjectClass *oc = oc_bvfind( value );
    216 	ObjectClass *asserted = oc_bvfind( a );
    217 
    218 	if( asserted == NULL ) {
    219 		if( OID_LEADCHAR( *a->bv_val ) ) {
    220 			/* OID form, return FALSE */
    221 			*matchp = 1;
    222 			return LDAP_SUCCESS;
    223 		}
    224 
    225 		/* desc form, return undefined */
    226 		return LDAP_INVALID_SYNTAX;
    227 	}
    228 
    229 	if ( oc == NULL ) {
    230 		/* unrecognized stored value */
    231 		return LDAP_INVALID_SYNTAX;
    232 	}
    233 
    234 	if( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX( flags ) ) {
    235 		*matchp = ( asserted != oc );
    236 	} else {
    237 		*matchp = !is_object_subclass( asserted, oc );
    238 	}
    239 
    240 	return LDAP_SUCCESS;
    241 }
    242 
    243 static int objectSubClassIndexer(
    244 	slap_mask_t use,
    245 	slap_mask_t mask,
    246 	Syntax *syntax,
    247 	MatchingRule *mr,
    248 	struct berval *prefix,
    249 	BerVarray values,
    250 	BerVarray *keysp,
    251 	void *ctx )
    252 {
    253 	int rc, noc, i;
    254 	BerVarray ocvalues;
    255 	ObjectClass **socs;
    256 
    257 	for( noc=0; values[noc].bv_val != NULL; noc++ ) {
    258 		/* just count em */;
    259 	}
    260 
    261 	/* over allocate */
    262 	socs = slap_sl_malloc( (noc+16) * sizeof( ObjectClass * ), ctx );
    263 
    264 	/* initialize */
    265 	for( i=0; i<noc; i++ ) {
    266 		socs[i] = oc_bvfind( &values[i] );
    267 	}
    268 
    269 	/* expand values */
    270 	for( i=0; i<noc; i++ ) {
    271 		int j;
    272 		ObjectClass *oc = socs[i];
    273 		if( oc == NULL || oc->soc_sups == NULL ) continue;
    274 
    275 		for( j=0; oc->soc_sups[j] != NULL; j++ ) {
    276 			int found = 0;
    277 			ObjectClass *sup = oc->soc_sups[j];
    278 			int k;
    279 
    280 			for( k=0; k<noc; k++ ) {
    281 				if( sup == socs[k] ) {
    282 					found++;
    283 					break;
    284 				}
    285 			}
    286 
    287 			if( !found ) {
    288 				socs = slap_sl_realloc( socs,
    289 					sizeof( ObjectClass * ) * (noc+2), ctx );
    290 
    291 				assert( k == noc );
    292 				socs[noc++] = sup;
    293 			}
    294 		}
    295 	}
    296 
    297 	ocvalues = slap_sl_malloc( sizeof( struct berval ) * (noc+1), ctx );
    298 	/* copy values */
    299 	for( i=0; i<noc; i++ ) {
    300 		if ( socs[i] )
    301 			ocvalues[i] = socs[i]->soc_cname;
    302 		else
    303 			ocvalues[i] = values[i];
    304 	}
    305 	BER_BVZERO( &ocvalues[i] );
    306 
    307 	rc = octetStringIndexer( use, mask, syntax, mr,
    308 		prefix, ocvalues, keysp, ctx );
    309 
    310 	slap_sl_free( ocvalues, ctx );
    311 	slap_sl_free( socs, ctx );
    312 	return rc;
    313 }
    314 
    315 #define objectSubClassFilter octetStringFilter
    316 
    317 static ObjectClassSchemaCheckFN rootDseObjectClass;
    318 static ObjectClassSchemaCheckFN aliasObjectClass;
    319 static ObjectClassSchemaCheckFN referralObjectClass;
    320 static ObjectClassSchemaCheckFN subentryObjectClass;
    321 #ifdef LDAP_DYNAMIC_OBJECTS
    322 static ObjectClassSchemaCheckFN dynamicObjectClass;
    323 #endif
    324 
    325 static struct slap_schema_oc_map {
    326 	char *ssom_name;
    327 	char *ssom_defn;
    328 	ObjectClassSchemaCheckFN *ssom_check;
    329 	slap_mask_t ssom_flags;
    330 	size_t ssom_offset;
    331 } oc_map[] = {
    332 	{ "top", "( 2.5.6.0 NAME 'top' "
    333 			"DESC 'top of the superclass chain' "
    334 			"ABSTRACT MUST objectClass )",
    335 		0, 0, offsetof(struct slap_internal_schema, si_oc_top) },
    336 	{ "extensibleObject", "( 1.3.6.1.4.1.1466.101.120.111 "
    337 			"NAME 'extensibleObject' "
    338 			"DESC 'RFC4512: extensible object' "
    339 			"SUP top AUXILIARY )",
    340 		0, SLAP_OC_OPERATIONAL,
    341 		offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
    342 	{ "alias", "( 2.5.6.1 NAME 'alias' "
    343 			"DESC 'RFC4512: an alias' "
    344 			"SUP top STRUCTURAL "
    345 			"MUST aliasedObjectName )",
    346 		aliasObjectClass, SLAP_OC_ALIAS|SLAP_OC_OPERATIONAL,
    347 		offsetof(struct slap_internal_schema, si_oc_alias) },
    348 	{ "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
    349 			"DESC 'namedref: named subordinate referral' "
    350 			"SUP top STRUCTURAL MUST ref )",
    351 		referralObjectClass, SLAP_OC_REFERRAL|SLAP_OC_OPERATIONAL,
    352 		offsetof(struct slap_internal_schema, si_oc_referral) },
    353 	{ "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
    354 			"NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
    355 			"DESC 'OpenLDAP Root DSE object' "
    356 			"SUP top STRUCTURAL MAY cn )",
    357 		rootDseObjectClass, SLAP_OC_OPERATIONAL,
    358 		offsetof(struct slap_internal_schema, si_oc_rootdse) },
    359 	{ "subentry", "( 2.5.17.0 NAME 'subentry' "
    360 			"DESC 'RFC3672: subentry' "
    361 			"SUP top STRUCTURAL "
    362 			"MUST ( cn $ subtreeSpecification ) )",
    363 		subentryObjectClass, SLAP_OC_SUBENTRY|SLAP_OC_OPERATIONAL,
    364 		offsetof(struct slap_internal_schema, si_oc_subentry) },
    365 	{ "subschema", "( 2.5.20.1 NAME 'subschema' "
    366 		"DESC 'RFC4512: controlling subschema (sub)entry' "
    367 		"AUXILIARY "
    368 		"MAY ( dITStructureRules $ nameForms $ dITContentRules $ "
    369 			"objectClasses $ attributeTypes $ matchingRules $ "
    370 			"matchingRuleUse ) )",
    371 		subentryObjectClass, SLAP_OC_OPERATIONAL,
    372 		offsetof(struct slap_internal_schema, si_oc_subschema) },
    373 #ifdef LDAP_COLLECTIVE_ATTRIBUTES
    374 	{ "collectiveAttributeSubentry", "( 2.5.17.2 "
    375 			"NAME 'collectiveAttributeSubentry' "
    376 			"DESC 'RFC3671: collective attribute subentry' "
    377 			"AUXILIARY )",
    378 		subentryObjectClass,
    379 		SLAP_OC_COLLECTIVEATTRIBUTESUBENTRY|SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
    380 		offsetof( struct slap_internal_schema,
    381 			si_oc_collectiveAttributeSubentry) },
    382 #endif
    383 #ifdef LDAP_DYNAMIC_OBJECTS
    384 	{ "dynamicObject", "( 1.3.6.1.4.1.1466.101.119.2 "
    385 			"NAME 'dynamicObject' "
    386 			"DESC 'RFC2589: Dynamic Object' "
    387 			"SUP top AUXILIARY )",
    388 		dynamicObjectClass, SLAP_OC_DYNAMICOBJECT,
    389 		offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
    390 #endif
    391 	{ "glue", "( 1.3.6.1.4.1.4203.666.3.4 "
    392 			"NAME 'glue' "
    393 			"DESC 'Glue Entry' "
    394 			"SUP top STRUCTURAL )",
    395 		0, SLAP_OC_GLUE|SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
    396 		offsetof(struct slap_internal_schema, si_oc_glue) },
    397 	{ "syncConsumerSubentry", "( 1.3.6.1.4.1.4203.666.3.5 "
    398 			"NAME 'syncConsumerSubentry' "
    399 			"DESC 'Persistent Info for SyncRepl Consumer' "
    400 			"AUXILIARY "
    401 			"MAY syncreplCookie )",
    402 		0, SLAP_OC_SYNCCONSUMERSUBENTRY|SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
    403 		offsetof(struct slap_internal_schema, si_oc_syncConsumerSubentry) },
    404 	{ "syncProviderSubentry", "( 1.3.6.1.4.1.4203.666.3.6 "
    405 			"NAME 'syncProviderSubentry' "
    406 			"DESC 'Persistent Info for SyncRepl Producer' "
    407 			"AUXILIARY "
    408 			"MAY contextCSN )",
    409 		0, SLAP_OC_SYNCPROVIDERSUBENTRY|SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
    410 		offsetof(struct slap_internal_schema, si_oc_syncProviderSubentry) },
    411 
    412 	{ NULL, NULL, NULL, 0, 0 }
    413 };
    414 
    415 static AttributeTypeSchemaCheckFN rootDseAttribute;
    416 static AttributeTypeSchemaCheckFN aliasAttribute;
    417 static AttributeTypeSchemaCheckFN referralAttribute;
    418 static AttributeTypeSchemaCheckFN subentryAttribute;
    419 static AttributeTypeSchemaCheckFN administrativeRoleAttribute;
    420 #ifdef LDAP_DYNAMIC_OBJECTS
    421 static AttributeTypeSchemaCheckFN dynamicAttribute;
    422 #endif
    423 
    424 static struct slap_schema_ad_map {
    425 	char *ssam_name;
    426 	char *ssam_defn;
    427 	AttributeTypeSchemaCheckFN *ssam_check;
    428 	slap_mask_t ssam_flags;
    429 	slap_syntax_validate_func *ssam_syn_validate;
    430 	slap_syntax_transform_func *ssam_syn_pretty;
    431 	slap_mr_convert_func *ssam_mr_convert;
    432 	slap_mr_normalize_func *ssam_mr_normalize;
    433 	slap_mr_match_func *ssam_mr_match;
    434 	slap_mr_indexer_func *ssam_mr_indexer;
    435 	slap_mr_filter_func *ssam_mr_filter;
    436 	size_t ssam_offset;
    437 } ad_map[] = {
    438 	{ "objectClass", "( 2.5.4.0 NAME 'objectClass' "
    439 			"DESC 'RFC4512: object classes of the entity' "
    440 			"EQUALITY objectIdentifierMatch "
    441 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
    442 		NULL, SLAP_AT_FINAL,
    443 		oidValidate, objectClassPretty,
    444 		NULL, NULL, objectSubClassMatch,
    445 			objectSubClassIndexer, objectSubClassFilter,
    446 		offsetof(struct slap_internal_schema, si_ad_objectClass) },
    447 
    448 	/* user entry operational attributes */
    449 	{ "structuralObjectClass", "( 2.5.21.9 NAME 'structuralObjectClass' "
    450 			"DESC 'RFC4512: structural object class of entry' "
    451 			"EQUALITY objectIdentifierMatch "
    452 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
    453 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    454 		NULL, 0,
    455 		oidValidate, objectClassPretty,
    456 		NULL, NULL, objectSubClassMatch,
    457 			objectSubClassIndexer, objectSubClassFilter,
    458 		offsetof(struct slap_internal_schema, si_ad_structuralObjectClass) },
    459 	{ "createTimestamp", "( 2.5.18.1 NAME 'createTimestamp' "
    460 			"DESC 'RFC4512: time which object was created' "
    461 			"EQUALITY generalizedTimeMatch "
    462 			"ORDERING generalizedTimeOrderingMatch "
    463 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
    464 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    465 		NULL, SLAP_AT_MANAGEABLE,
    466 		NULL, NULL,
    467 		NULL, NULL, NULL, NULL, NULL,
    468 		offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
    469 	{ "modifyTimestamp", "( 2.5.18.2 NAME 'modifyTimestamp' "
    470 			"DESC 'RFC4512: time which object was last modified' "
    471 			"EQUALITY generalizedTimeMatch "
    472 			"ORDERING generalizedTimeOrderingMatch "
    473 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
    474 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    475 		NULL, SLAP_AT_MANAGEABLE,
    476 		NULL, NULL,
    477 		NULL, NULL, NULL, NULL, NULL,
    478 		offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
    479 	{ "creatorsName", "( 2.5.18.3 NAME 'creatorsName' "
    480 			"DESC 'RFC4512: name of creator' "
    481 			"EQUALITY distinguishedNameMatch "
    482 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    483 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    484 		NULL, SLAP_AT_MANAGEABLE,
    485 		NULL, NULL,
    486 		NULL, NULL, NULL, NULL, NULL,
    487 		offsetof(struct slap_internal_schema, si_ad_creatorsName) },
    488 	{ "modifiersName", "( 2.5.18.4 NAME 'modifiersName' "
    489 			"DESC 'RFC4512: name of last modifier' "
    490 			"EQUALITY distinguishedNameMatch "
    491 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    492 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    493 		NULL, SLAP_AT_MANAGEABLE,
    494 		NULL, NULL,
    495 		NULL, NULL, NULL, NULL, NULL,
    496 		offsetof(struct slap_internal_schema, si_ad_modifiersName) },
    497 	{ "hasSubordinates", "( 2.5.18.9 NAME 'hasSubordinates' "
    498 			"DESC 'X.501: entry has children' "
    499 			"EQUALITY booleanMatch "
    500 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
    501 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    502 		NULL, SLAP_AT_DYNAMIC,
    503 		NULL, NULL,
    504 		NULL, NULL, NULL, NULL, NULL,
    505 		offsetof(struct slap_internal_schema, si_ad_hasSubordinates) },
    506 	{ "subschemaSubentry", "( 2.5.18.10 NAME 'subschemaSubentry' "
    507 			"DESC 'RFC4512: name of controlling subschema entry' "
    508 			"EQUALITY distinguishedNameMatch "
    509 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE "
    510 			"NO-USER-MODIFICATION USAGE directoryOperation )",
    511 		NULL, SLAP_AT_DYNAMIC,
    512 		NULL, NULL,
    513 		NULL, NULL, NULL, NULL, NULL,
    514 		offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
    515 #ifdef LDAP_COLLECTIVE_ATTRIBUTES
    516 	{ "collectiveAttributeSubentries", "( 2.5.18.12 "
    517 			"NAME 'collectiveAttributeSubentries' "
    518 			"DESC 'RFC3671: collective attribute subentries' "
    519 			"EQUALITY distinguishedNameMatch "
    520 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    521 			"NO-USER-MODIFICATION USAGE directoryOperation )",
    522 		NULL, SLAP_AT_HIDE,
    523 		NULL, NULL,
    524 		NULL, NULL, NULL, NULL, NULL,
    525 		offsetof(struct slap_internal_schema, si_ad_collectiveSubentries) },
    526 	{ "collectiveExclusions", "( 2.5.18.7 NAME 'collectiveExclusions' "
    527 			"DESC 'RFC3671: collective attribute exclusions' "
    528 			"EQUALITY objectIdentifierMatch "
    529 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
    530 			"USAGE directoryOperation )",
    531 		NULL, SLAP_AT_HIDE,
    532 		NULL, NULL,
    533 		NULL, NULL, NULL, NULL, NULL,
    534 		offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
    535 #endif
    536 
    537 	{ "entryDN", "( 1.3.6.1.1.20 NAME 'entryDN' "
    538 			"DESC 'DN of the entry' "
    539 			"EQUALITY distinguishedNameMatch "
    540 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    541 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    542 		NULL, SLAP_AT_DYNAMIC,
    543 		NULL, NULL,
    544 		NULL, NULL, NULL, NULL, NULL,
    545 		offsetof(struct slap_internal_schema, si_ad_entryDN) },
    546 	{ "entryUUID", "( 1.3.6.1.1.16.4 NAME 'entryUUID' "
    547 			"DESC 'UUID of the entry' "
    548 			"EQUALITY UUIDMatch "
    549 			"ORDERING UUIDOrderingMatch "
    550 			"SYNTAX 1.3.6.1.1.16.1 "
    551 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    552 		NULL, SLAP_AT_MANAGEABLE,
    553 		NULL, NULL,
    554 		NULL, NULL, NULL, NULL, NULL,
    555 		offsetof(struct slap_internal_schema, si_ad_entryUUID) },
    556 	{ "entryCSN", "( 1.3.6.1.4.1.4203.666.1.7 NAME 'entryCSN' "
    557 			"DESC 'change sequence number of the entry content' "
    558 			"EQUALITY CSNMatch "
    559 			"ORDERING CSNOrderingMatch "
    560 			"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1{64} "
    561 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    562 		NULL, SLAP_AT_HIDE,
    563 		NULL, NULL,
    564 		NULL, NULL, NULL, NULL, NULL,
    565 		offsetof(struct slap_internal_schema, si_ad_entryCSN) },
    566 	{ "namingCSN", "( 1.3.6.1.4.1.4203.666.1.13 NAME 'namingCSN' "
    567 			"DESC 'change sequence number of the entry naming (RDN)' "
    568 			"EQUALITY CSNMatch "
    569 			"ORDERING CSNOrderingMatch "
    570 			"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1{64} "
    571 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    572 		NULL, SLAP_AT_HIDE,
    573 		NULL, NULL,
    574 		NULL, NULL, NULL, NULL, NULL,
    575 		offsetof(struct slap_internal_schema, si_ad_namingCSN) },
    576 
    577 #ifdef LDAP_SUPERIOR_UUID
    578 	{ "superiorUUID", "( 1.3.6.1.4.1.4203.666.1.11 NAME 'superiorUUID' "
    579 			"DESC 'UUID of the superior entry' "
    580 			"EQUALITY UUIDMatch "
    581 			"ORDERING UUIDOrderingMatch "
    582 			"SYNTAX 1.3.6.1.1.16.1 "
    583 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
    584 		NULL, SLAP_AT_HIDE,
    585 		NULL, NULL,
    586 		NULL, NULL, NULL, NULL, NULL,
    587 		offsetof(struct slap_internal_schema, si_ad_superiorUUID) },
    588 #endif
    589 
    590 	{ "syncreplCookie", "( 1.3.6.1.4.1.4203.666.1.23 "
    591 			"NAME 'syncreplCookie' "
    592 			"DESC 'syncrepl Cookie for shadow copy' "
    593 			"EQUALITY octetStringMatch "
    594 			"ORDERING octetStringOrderingMatch "
    595 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 "
    596 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
    597 		NULL, SLAP_AT_HIDE,
    598 		NULL, NULL,
    599 		NULL, NULL, NULL, NULL, NULL,
    600 		offsetof(struct slap_internal_schema, si_ad_syncreplCookie) },
    601 
    602 	{ "contextCSN", "( 1.3.6.1.4.1.4203.666.1.25 "
    603 			"NAME 'contextCSN' "
    604 			"DESC 'the largest committed CSN of a context' "
    605 			"EQUALITY CSNMatch "
    606 			"ORDERING CSNOrderingMatch "
    607 			"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1{64} "
    608 			"NO-USER-MODIFICATION USAGE dSAOperation )",
    609 		NULL, SLAP_AT_HIDE,
    610 		NULL, NULL,
    611 		NULL, NULL, NULL, NULL, NULL,
    612 		offsetof(struct slap_internal_schema, si_ad_contextCSN) },
    613 
    614 #ifdef LDAP_SYNC_TIMESTAMP
    615 	{ "syncTimestamp", "( 1.3.6.1.4.1.4203.666.1.26 NAME 'syncTimestamp' "
    616 			"DESC 'Time which object was replicated' "
    617 			"EQUALITY generalizedTimeMatch "
    618 			"ORDERING generalizedTimeOrderingMatch "
    619 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
    620 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
    621 		NULL, 0,
    622 		NULL, NULL,
    623 		NULL, NULL, NULL, NULL, NULL,
    624 		offsetof(struct slap_internal_schema, si_ad_syncTimestamp) },
    625 #endif
    626 
    627 	/* root DSE attributes */
    628 	{ "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' "
    629 			"DESC 'RFC4512: alternative servers' "
    630 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )",
    631 		rootDseAttribute, 0,
    632 		NULL, NULL,
    633 		NULL, NULL, NULL, NULL, NULL,
    634 		offsetof(struct slap_internal_schema, si_ad_altServer) },
    635 	{ "namingContexts", "( 1.3.6.1.4.1.1466.101.120.5 "
    636 			"NAME 'namingContexts' "
    637 			"DESC 'RFC4512: naming contexts' "
    638 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )",
    639 		rootDseAttribute, 0,
    640 		NULL, NULL,
    641 		NULL, NULL, NULL, NULL, NULL,
    642 		offsetof(struct slap_internal_schema, si_ad_namingContexts) },
    643 	{ "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
    644 			"NAME 'supportedControl' "
    645 			"DESC 'RFC4512: supported controls' "
    646 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
    647 		rootDseAttribute, 0,
    648 		NULL, NULL,
    649 		NULL, NULL, NULL, NULL, NULL,
    650 		offsetof(struct slap_internal_schema, si_ad_supportedControl) },
    651 	{ "supportedExtension", "( 1.3.6.1.4.1.1466.101.120.7 "
    652 			"NAME 'supportedExtension' "
    653 			"DESC 'RFC4512: supported extended operations' "
    654 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
    655 		rootDseAttribute, 0,
    656 		NULL, NULL,
    657 		NULL, NULL, NULL, NULL, NULL,
    658 		offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
    659 	{ "supportedLDAPVersion", "( 1.3.6.1.4.1.1466.101.120.15 "
    660 			"NAME 'supportedLDAPVersion' "
    661 			"DESC 'RFC4512: supported LDAP versions' "
    662 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )",
    663 		rootDseAttribute, 0,
    664 		NULL, NULL,
    665 		NULL, NULL, NULL, NULL, NULL,
    666 		offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
    667 	{ "supportedSASLMechanisms", "( 1.3.6.1.4.1.1466.101.120.14 "
    668 			"NAME 'supportedSASLMechanisms' "
    669 			"DESC 'RFC4512: supported SASL mechanisms'"
    670 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )",
    671 		rootDseAttribute, 0,
    672 		NULL, NULL,
    673 		NULL, NULL, NULL, NULL, NULL,
    674 		offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
    675 	{ "supportedFeatures", "( 1.3.6.1.4.1.4203.1.3.5 "
    676 			"NAME 'supportedFeatures' "
    677 			"DESC 'RFC4512: features supported by the server' "
    678 			"EQUALITY objectIdentifierMatch "
    679 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
    680 			"USAGE dSAOperation )",
    681 		rootDseAttribute, 0,
    682 		NULL, NULL,
    683 		NULL, NULL, NULL, NULL, NULL,
    684 		offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
    685 	{ "monitorContext", "( 1.3.6.1.4.1.4203.666.1.10 "
    686 			"NAME 'monitorContext' "
    687 			"DESC 'monitor context' "
    688 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    689 			"EQUALITY distinguishedNameMatch "
    690 			"SINGLE-VALUE NO-USER-MODIFICATION "
    691 			"USAGE dSAOperation )",
    692 		rootDseAttribute, SLAP_AT_HIDE,
    693 		NULL, NULL,
    694 		NULL, NULL, NULL, NULL, NULL,
    695 		offsetof(struct slap_internal_schema, si_ad_monitorContext) },
    696 	{ "configContext", "( 1.3.6.1.4.1.4203.1.12.2.1 "
    697 			"NAME 'configContext' "
    698 			"DESC 'config context' "
    699 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    700 			"EQUALITY distinguishedNameMatch "
    701 			"SINGLE-VALUE NO-USER-MODIFICATION "
    702 			"USAGE dSAOperation )",
    703 		rootDseAttribute, SLAP_AT_HIDE,
    704 		NULL, NULL,
    705 		NULL, NULL, NULL, NULL, NULL,
    706 		offsetof(struct slap_internal_schema, si_ad_configContext) },
    707 	{ "vendorName", "( 1.3.6.1.1.4 NAME 'vendorName' "
    708 			"DESC 'RFC3045: name of implementation vendor' "
    709 			"EQUALITY caseExactMatch "
    710 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
    711 			"SINGLE-VALUE NO-USER-MODIFICATION "
    712 			"USAGE dSAOperation )",
    713 		rootDseAttribute, 0,
    714 		NULL, NULL,
    715 		NULL, NULL, NULL, NULL, NULL,
    716 		offsetof(struct slap_internal_schema, si_ad_vendorName) },
    717 	{ "vendorVersion", "( 1.3.6.1.1.5 NAME 'vendorVersion' "
    718 			"DESC 'RFC3045: version of implementation' "
    719 			"EQUALITY caseExactMatch "
    720 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
    721 			"SINGLE-VALUE NO-USER-MODIFICATION "
    722 			"USAGE dSAOperation )",
    723 		rootDseAttribute, 0,
    724 		NULL, NULL,
    725 		NULL, NULL, NULL, NULL, NULL,
    726 		offsetof(struct slap_internal_schema, si_ad_vendorVersion) },
    727 
    728 	/* subentry attributes */
    729 	{ "administrativeRole", "( 2.5.18.5 NAME 'administrativeRole' "
    730 			"DESC 'RFC3672: administrative role' "
    731 			"EQUALITY objectIdentifierMatch "
    732 			"USAGE directoryOperation "
    733 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
    734 		administrativeRoleAttribute, SLAP_AT_HIDE,
    735 		NULL, NULL,
    736 		NULL, NULL, NULL, NULL, NULL,
    737 		offsetof(struct slap_internal_schema, si_ad_administrativeRole) },
    738 	{ "subtreeSpecification", "( 2.5.18.6 NAME 'subtreeSpecification' "
    739 			"DESC 'RFC3672: subtree specification' "
    740 			"SINGLE-VALUE "
    741 			"USAGE directoryOperation "
    742 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.45 )",
    743 		subentryAttribute, SLAP_AT_HIDE,
    744 		NULL, NULL,
    745 		NULL, NULL, NULL, NULL, NULL,
    746 		offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
    747 
    748 	/* subschema subentry attributes */
    749 	{ "dITStructureRules", "( 2.5.21.1 NAME 'dITStructureRules' "
    750 			"DESC 'RFC4512: DIT structure rules' "
    751 			"EQUALITY integerFirstComponentMatch "
    752 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 "
    753 			"USAGE directoryOperation ) ",
    754 		subentryAttribute, SLAP_AT_HIDE,
    755 		NULL, NULL,
    756 		NULL, NULL, NULL, NULL, NULL,
    757 		offsetof(struct slap_internal_schema, si_ad_ditStructureRules) },
    758 	{ "dITContentRules", "( 2.5.21.2 NAME 'dITContentRules' "
    759 			"DESC 'RFC4512: DIT content rules' "
    760 			"EQUALITY objectIdentifierFirstComponentMatch "
    761 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )",
    762 		subentryAttribute, SLAP_AT_HIDE,
    763 		oidValidate, NULL,
    764 		NULL, NULL, objectClassMatch, NULL, NULL,
    765 		offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
    766 	{ "matchingRules", "( 2.5.21.4 NAME 'matchingRules' "
    767 			"DESC 'RFC4512: matching rules' "
    768 			"EQUALITY objectIdentifierFirstComponentMatch "
    769 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )",
    770 		subentryAttribute, 0,
    771 		oidValidate, NULL,
    772 		NULL, NULL, matchingRuleMatch, NULL, NULL,
    773 		offsetof(struct slap_internal_schema, si_ad_matchingRules) },
    774 	{ "attributeTypes", "( 2.5.21.5 NAME 'attributeTypes' "
    775 			"DESC 'RFC4512: attribute types' "
    776 			"EQUALITY objectIdentifierFirstComponentMatch "
    777 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )",
    778 		subentryAttribute, 0,
    779 		oidValidate, NULL,
    780 		NULL, NULL, attributeTypeMatch, NULL, NULL,
    781 		offsetof(struct slap_internal_schema, si_ad_attributeTypes) },
    782 	{ "objectClasses", "( 2.5.21.6 NAME 'objectClasses' "
    783 			"DESC 'RFC4512: object classes' "
    784 			"EQUALITY objectIdentifierFirstComponentMatch "
    785 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )",
    786 		subentryAttribute, 0,
    787 		oidValidate, NULL,
    788 		NULL, NULL, objectClassMatch, NULL, NULL,
    789 		offsetof(struct slap_internal_schema, si_ad_objectClasses) },
    790 	{ "nameForms", "( 2.5.21.7 NAME 'nameForms' "
    791 			"DESC 'RFC4512: name forms ' "
    792 			"EQUALITY objectIdentifierFirstComponentMatch "
    793 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )",
    794 		subentryAttribute, SLAP_AT_HIDE,
    795 		NULL, NULL,
    796 		NULL, NULL, NULL, NULL, NULL,
    797 		offsetof(struct slap_internal_schema, si_ad_nameForms) },
    798 	{ "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
    799 			"DESC 'RFC4512: matching rule uses' "
    800 			"EQUALITY objectIdentifierFirstComponentMatch "
    801 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
    802 		subentryAttribute, 0,
    803 		oidValidate, NULL,
    804 		NULL, NULL, matchingRuleMatch, NULL, NULL,
    805 		offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
    806 
    807 	{ "ldapSyntaxes", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' "
    808 			"DESC 'RFC4512: LDAP syntaxes' "
    809 			"EQUALITY objectIdentifierFirstComponentMatch "
    810 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )",
    811 		subentryAttribute, 0,
    812 		NULL, NULL,
    813 		NULL, NULL, NULL, NULL, NULL,
    814 		offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },
    815 
    816 	/* knowledge information */
    817 	{ "aliasedObjectName", "( 2.5.4.1 "
    818 			"NAME ( 'aliasedObjectName' 'aliasedEntryName' ) "
    819 			"DESC 'RFC4512: name of aliased object' "
    820 			"EQUALITY distinguishedNameMatch "
    821 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
    822 		aliasAttribute, SLAP_AT_FINAL,
    823 		NULL, NULL,
    824 		NULL, NULL, NULL, NULL, NULL,
    825 		offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
    826 	{ "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
    827 			"DESC 'RFC3296: subordinate referral URL' "
    828 			"EQUALITY caseExactMatch "
    829 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
    830 			"USAGE distributedOperation )",
    831 		referralAttribute, 0,
    832 		NULL, NULL,
    833 		NULL, NULL, NULL, NULL, NULL,
    834 		offsetof(struct slap_internal_schema, si_ad_ref) },
    835 
    836 	/* access control internals */
    837 	{ "entry", "( 1.3.6.1.4.1.4203.1.3.1 "
    838 			"NAME 'entry' "
    839 			"DESC 'OpenLDAP ACL entry pseudo-attribute' "
    840 			"SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
    841 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
    842 		NULL, SLAP_AT_HIDE,
    843 		NULL, NULL,
    844 		NULL, NULL, NULL, NULL, NULL,
    845 		offsetof(struct slap_internal_schema, si_ad_entry) },
    846 	{ "children", "( 1.3.6.1.4.1.4203.1.3.2 "
    847 			"NAME 'children' "
    848 			"DESC 'OpenLDAP ACL children pseudo-attribute' "
    849 			"SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
    850 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
    851 		NULL, SLAP_AT_HIDE,
    852 		NULL, NULL,
    853 		NULL, NULL, NULL, NULL, NULL,
    854 		offsetof(struct slap_internal_schema, si_ad_children) },
    855 
    856 	/* access control externals */
    857 	{ "authzTo", "( 1.3.6.1.4.1.4203.666.1.8 "
    858 			"NAME ( 'authzTo' 'saslAuthzTo' ) "
    859 			"DESC 'proxy authorization targets' "
    860 			"EQUALITY authzMatch "
    861 			"SYNTAX 1.3.6.1.4.1.4203.666.2.7 "
    862 			"X-ORDERED 'VALUES' "
    863 			"USAGE distributedOperation )",
    864 		NULL, SLAP_AT_HIDE,
    865 		NULL, NULL,
    866 		NULL, NULL, NULL, NULL, NULL,
    867 		offsetof(struct slap_internal_schema, si_ad_saslAuthzTo) },
    868 	{ "authzFrom", "( 1.3.6.1.4.1.4203.666.1.9 "
    869 			"NAME ( 'authzFrom' 'saslAuthzFrom' ) "
    870 			"DESC 'proxy authorization sources' "
    871 			"EQUALITY authzMatch "
    872 			"SYNTAX 1.3.6.1.4.1.4203.666.2.7 "
    873 			"X-ORDERED 'VALUES' "
    874 			"USAGE distributedOperation )",
    875 		NULL, SLAP_AT_HIDE,
    876 		NULL, NULL,
    877 		NULL, NULL, NULL, NULL, NULL,
    878 		offsetof(struct slap_internal_schema, si_ad_saslAuthzFrom) },
    879 
    880 #ifdef LDAP_DYNAMIC_OBJECTS
    881 	{ "entryTtl", "( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl' "
    882 			"DESC 'RFC2589: entry time-to-live' "
    883 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE "
    884 			"NO-USER-MODIFICATION USAGE dSAOperation )",
    885 		dynamicAttribute, SLAP_AT_MANAGEABLE,
    886 		NULL, NULL,
    887 		NULL, NULL, NULL, NULL, NULL,
    888 		offsetof(struct slap_internal_schema, si_ad_entryTtl) },
    889 	{ "dynamicSubtrees", "( 1.3.6.1.4.1.1466.101.119.4 "
    890 			"NAME 'dynamicSubtrees' "
    891 			"DESC 'RFC2589: dynamic subtrees' "
    892 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
    893 			"USAGE dSAOperation )",
    894 		rootDseAttribute, 0,
    895 		NULL, NULL,
    896 		NULL, NULL, NULL, NULL, NULL,
    897 		offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },
    898 #endif
    899 
    900 	/* userApplication attributes (which system schema depends upon) */
    901 	{ "distinguishedName", "( 2.5.4.49 NAME 'distinguishedName' "
    902 			"DESC 'RFC4519: common supertype of DN attributes' "
    903 			"EQUALITY distinguishedNameMatch "
    904 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
    905 		NULL, SLAP_AT_ABSTRACT,
    906 		NULL, NULL,
    907 		NULL, NULL, NULL, NULL, NULL,
    908 		offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
    909 	{ "name", "( 2.5.4.41 NAME 'name' "
    910 			"DESC 'RFC4519: common supertype of name attributes' "
    911 			"EQUALITY caseIgnoreMatch "
    912 			"SUBSTR caseIgnoreSubstringsMatch "
    913 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )",
    914 		NULL, SLAP_AT_ABSTRACT,
    915 		NULL, NULL,
    916 		NULL, NULL, NULL, NULL, NULL,
    917 		offsetof(struct slap_internal_schema, si_ad_name) },
    918 	{ "cn", "( 2.5.4.3 NAME ( 'cn' 'commonName' ) "
    919 			"DESC 'RFC4519: common name(s) for which the entity is known by' "
    920 			"SUP name )",
    921 		NULL, 0,
    922 		NULL, NULL,
    923 		NULL, NULL, NULL, NULL, NULL,
    924 		offsetof(struct slap_internal_schema, si_ad_cn) },
    925 	{ "uid", "( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' ) "
    926 			"DESC 'RFC4519: user identifier' "
    927 			"EQUALITY caseIgnoreMatch "
    928 			"SUBSTR caseIgnoreSubstringsMatch "
    929 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )",
    930 		NULL, 0,
    931 		NULL, NULL,
    932 		NULL, NULL, NULL, NULL, NULL,
    933 		offsetof(struct slap_internal_schema, si_ad_uid) },
    934 	{ "uidNumber", /* for ldapi:// */
    935 		"( 1.3.6.1.1.1.1.0 NAME 'uidNumber' "
    936     		"DESC 'RFC2307: An integer uniquely identifying a user "
    937 				"in an administrative domain' "
    938     		"EQUALITY integerMatch "
    939     		"ORDERING integerOrderingMatch "
    940     		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )",
    941 		NULL, 0,
    942 		NULL, NULL,
    943 		NULL, NULL, NULL, NULL, NULL,
    944 		offsetof(struct slap_internal_schema, si_ad_uidNumber) },
    945 	{ "gidNumber", /* for ldapi:// */
    946 		"( 1.3.6.1.1.1.1.1 NAME 'gidNumber' "
    947     		"DESC 'RFC2307: An integer uniquely identifying a group "
    948 				"in an administrative domain' "
    949     		"EQUALITY integerMatch "
    950     		"ORDERING integerOrderingMatch "
    951     		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )",
    952 		NULL, 0,
    953 		NULL, NULL,
    954 		NULL, NULL, NULL, NULL, NULL,
    955 		offsetof(struct slap_internal_schema, si_ad_gidNumber) },
    956 	{ "userPassword", "( 2.5.4.35 NAME 'userPassword' "
    957 			"DESC 'RFC4519/2307: password of user' "
    958 			"EQUALITY octetStringMatch "
    959 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )",
    960 		NULL, 0,
    961 		NULL, NULL,
    962 		NULL, NULL, NULL, NULL, NULL,
    963 		offsetof(struct slap_internal_schema, si_ad_userPassword) },
    964 
    965 	{ "labeledURI", "( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI' "
    966 			"DESC 'RFC2079: Uniform Resource Identifier with optional label' "
    967 			"EQUALITY caseExactMatch "
    968 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
    969 		NULL, 0,
    970 		NULL, NULL,
    971 		NULL, NULL, NULL, NULL, NULL,
    972 		offsetof(struct slap_internal_schema, si_ad_labeledURI) },
    973 
    974 #ifdef SLAPD_AUTHPASSWD
    975 	{ "authPassword", "( 1.3.6.1.4.1.4203.1.3.4 "
    976 			"NAME 'authPassword' "
    977 			"DESC 'RFC3112: authentication password attribute' "
    978 			"EQUALITY 1.3.6.1.4.1.4203.1.2.2 "
    979 			"SYNTAX 1.3.6.1.4.1.4203.1.1.2 )",
    980 		NULL, 0,
    981 		NULL, NULL,
    982 		NULL, NULL, NULL, NULL, NULL,
    983 		offsetof(struct slap_internal_schema, si_ad_authPassword) },
    984 	{ "supportedAuthPasswordSchemes", "( 1.3.6.1.4.1.4203.1.3.3 "
    985 			"NAME 'supportedAuthPasswordSchemes' "
    986 			"DESC 'RFC3112: supported authPassword schemes' "
    987 			"EQUALITY caseExactIA5Match "
    988 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} "
    989 			"USAGE dSAOperation )",
    990 		subschemaAttribute, 0,
    991 		NULL, NULL,
    992 		NULL, NULL, NULL, NULL, NULL,
    993 		offsetof(struct slap_internal_schema, si_ad_authPasswordSchemes) },
    994 #endif
    995 
    996 	{ "description", "( 2.5.4.13 NAME 'description' "
    997 			"DESC 'RFC4519: descriptive information' "
    998 			"EQUALITY caseIgnoreMatch "
    999 			"SUBSTR caseIgnoreSubstringsMatch "
   1000 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )",
   1001 		NULL, 0,
   1002 		NULL, NULL,
   1003 		NULL, NULL, NULL, NULL, NULL,
   1004 		offsetof(struct slap_internal_schema, si_ad_description) },
   1005 
   1006 	{ "seeAlso", "( 2.5.4.34 NAME 'seeAlso' "
   1007 			"DESC 'RFC4519: DN of related object' "
   1008 			"SUP distinguishedName )",
   1009 		NULL, 0,
   1010 		NULL, NULL,
   1011 		NULL, NULL, NULL, NULL, NULL,
   1012 		offsetof(struct slap_internal_schema, si_ad_seeAlso) },
   1013 
   1014 	{ NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 }
   1015 };
   1016 
   1017 static AttributeType slap_at_undefined = {
   1018 	{ "1.1.1", NULL, "Catchall for undefined attribute types", 1, NULL,
   1019 		NULL, NULL, NULL, NULL,
   1020 		0, 0, 0, 1, LDAP_SCHEMA_DSA_OPERATION, NULL }, /* LDAPAttributeType */
   1021 	BER_BVC("UNDEFINED"), /* cname */
   1022 	NULL, /* sup */
   1023 	NULL, /* subtypes */
   1024 	NULL, NULL, NULL, NULL,	/* matching rules routines */
   1025 	NULL, /* syntax (will be set later to "octetString") */
   1026 	NULL, /* schema check function */
   1027 	NULL, /* oidmacro */
   1028 	NULL, /* soidmacro */
   1029 	SLAP_AT_ABSTRACT|SLAP_AT_FINAL,	/* mask */
   1030 	{ NULL }, /* next */
   1031 	NULL /* attribute description */
   1032 	/* mutex (don't know how to initialize it :) */
   1033 };
   1034 
   1035 static AttributeType slap_at_proxied = {
   1036 	{ "1.1.1", NULL, "Catchall for undefined proxied attribute types", 1, NULL,
   1037 		NULL, NULL, NULL, NULL,
   1038 		0, 0, 0, 0, LDAP_SCHEMA_USER_APPLICATIONS, NULL }, /* LDAPAttributeType */
   1039 	BER_BVC("PROXIED"), /* cname */
   1040 	NULL, /* sup */
   1041 	NULL, /* subtypes */
   1042 	NULL, NULL, NULL, NULL,	/* matching rules routines (will be set later) */
   1043 	NULL, /* syntax (will be set later to "octetString") */
   1044 	NULL, /* schema check function */
   1045 	NULL, /* oidmacro */
   1046 	NULL, /* soidmacro */
   1047 	SLAP_AT_ABSTRACT|SLAP_AT_FINAL,	/* mask */
   1048 	{ NULL }, /* next */
   1049 	NULL /* attribute description */
   1050 	/* mutex (don't know how to initialize it :) */
   1051 };
   1052 
   1053 static struct slap_schema_mr_map {
   1054 	char *ssmm_name;
   1055 	size_t ssmm_offset;
   1056 } mr_map[] = {
   1057 	{ "caseExactIA5Match",
   1058 		offsetof(struct slap_internal_schema, si_mr_caseExactIA5Match) },
   1059 	{ "caseExactMatch",
   1060 		offsetof(struct slap_internal_schema, si_mr_caseExactMatch) },
   1061 	{ "caseExactSubstringsMatch",
   1062 		offsetof(struct slap_internal_schema, si_mr_caseExactSubstringsMatch) },
   1063 	{ "distinguishedNameMatch",
   1064 		offsetof(struct slap_internal_schema, si_mr_distinguishedNameMatch) },
   1065 	{ "dnSubtreeMatch",
   1066 		offsetof(struct slap_internal_schema, si_mr_dnSubtreeMatch) },
   1067 	{ "dnOneLevelMatch",
   1068 		offsetof(struct slap_internal_schema, si_mr_dnOneLevelMatch) },
   1069 	{ "dnSubordinateMatch",
   1070 		offsetof(struct slap_internal_schema, si_mr_dnSubordinateMatch) },
   1071 	{ "dnSuperiorMatch",
   1072 		offsetof(struct slap_internal_schema, si_mr_dnSuperiorMatch) },
   1073 	{ "integerMatch",
   1074 		offsetof(struct slap_internal_schema, si_mr_integerMatch) },
   1075 	{ "integerFirstComponentMatch",
   1076 		offsetof(struct slap_internal_schema,
   1077 			si_mr_integerFirstComponentMatch) },
   1078 	{ "objectIdentifierFirstComponentMatch",
   1079 		offsetof(struct slap_internal_schema,
   1080 			si_mr_objectIdentifierFirstComponentMatch) },
   1081 	{ "caseIgnoreMatch",
   1082 		offsetof(struct slap_internal_schema, si_mr_caseIgnoreMatch) },
   1083 	{ "caseIgnoreListMatch",
   1084 		offsetof(struct slap_internal_schema, si_mr_caseIgnoreListMatch) },
   1085 	{ NULL, 0 }
   1086 };
   1087 
   1088 static struct slap_schema_syn_map {
   1089 	char *sssm_name;
   1090 	size_t sssm_offset;
   1091 } syn_map[] = {
   1092 	{ "1.3.6.1.4.1.1466.115.121.1.15",
   1093 		offsetof(struct slap_internal_schema, si_syn_directoryString) },
   1094 	{ "1.3.6.1.4.1.1466.115.121.1.12",
   1095 		offsetof(struct slap_internal_schema, si_syn_distinguishedName) },
   1096 	{ "1.3.6.1.4.1.1466.115.121.1.27",
   1097 		offsetof(struct slap_internal_schema, si_syn_integer) },
   1098 	{ "1.3.6.1.4.1.1466.115.121.1.40",
   1099 		offsetof(struct slap_internal_schema, si_syn_octetString) },
   1100 	{ "1.3.6.1.4.1.1466.115.121.1.3",
   1101 		offsetof(struct slap_internal_schema, si_syn_attributeTypeDesc) },
   1102 	{ "1.3.6.1.4.1.1466.115.121.1.16",
   1103 		offsetof(struct slap_internal_schema, si_syn_ditContentRuleDesc) },
   1104 	{ "1.3.6.1.4.1.1466.115.121.1.54",
   1105 		offsetof(struct slap_internal_schema, si_syn_ldapSyntaxDesc) },
   1106 	{ "1.3.6.1.4.1.1466.115.121.1.30",
   1107 		offsetof(struct slap_internal_schema, si_syn_matchingRuleDesc) },
   1108 	{ "1.3.6.1.4.1.1466.115.121.1.31",
   1109 		offsetof(struct slap_internal_schema, si_syn_matchingRuleUseDesc) },
   1110 	{ "1.3.6.1.4.1.1466.115.121.1.35",
   1111 		offsetof(struct slap_internal_schema, si_syn_nameFormDesc) },
   1112 	{ "1.3.6.1.4.1.1466.115.121.1.37",
   1113 		offsetof(struct slap_internal_schema, si_syn_objectClassDesc) },
   1114 	{ "1.3.6.1.4.1.1466.115.121.1.17",
   1115 		offsetof(struct slap_internal_schema, si_syn_ditStructureRuleDesc) },
   1116 	{ NULL, 0 }
   1117 };
   1118 
   1119 int
   1120 slap_schema_load( void )
   1121 {
   1122 	int i;
   1123 
   1124 	for( i=0; syn_map[i].sssm_name; i++ ) {
   1125 		Syntax ** synp = (Syntax **)
   1126 			&(((char *) &slap_schema)[syn_map[i].sssm_offset]);
   1127 
   1128 		assert( *synp == NULL );
   1129 
   1130 		*synp = syn_find( syn_map[i].sssm_name );
   1131 
   1132 		if( *synp == NULL ) {
   1133 			fprintf( stderr, "slap_schema_load: Syntax: "
   1134 				"No syntax \"%s\" defined in schema\n",
   1135 				syn_map[i].sssm_name );
   1136 			return LDAP_INVALID_SYNTAX;
   1137 		}
   1138 	}
   1139 
   1140 	for( i=0; mr_map[i].ssmm_name; i++ ) {
   1141 		MatchingRule ** mrp = (MatchingRule **)
   1142 			&(((char *) &slap_schema)[mr_map[i].ssmm_offset]);
   1143 
   1144 		assert( *mrp == NULL );
   1145 
   1146 		*mrp = mr_find( mr_map[i].ssmm_name );
   1147 
   1148 		if( *mrp == NULL ) {
   1149 			fprintf( stderr, "slap_schema_load: MatchingRule: "
   1150 				"No matching rule \"%s\" defined in schema\n",
   1151 				mr_map[i].ssmm_name );
   1152 			return LDAP_INAPPROPRIATE_MATCHING;
   1153 		}
   1154 	}
   1155 
   1156 	slap_at_undefined.sat_syntax = slap_schema.si_syn_octetString;
   1157 	slap_schema.si_at_undefined = &slap_at_undefined;
   1158 
   1159 	slap_at_proxied.sat_equality = mr_find( "octetStringMatch" );
   1160 	slap_at_proxied.sat_approx = mr_find( "octetStringMatch" );
   1161 	slap_at_proxied.sat_ordering = mr_find( "octetStringOrderingMatch" );
   1162 	slap_at_proxied.sat_substr = mr_find( "octetStringSubstringsMatch" );
   1163 	slap_at_proxied.sat_syntax = slap_schema.si_syn_octetString;
   1164 	slap_schema.si_at_proxied = &slap_at_proxied;
   1165 
   1166 	ldap_pvt_thread_mutex_init( &ad_index_mutex );
   1167 	ldap_pvt_thread_mutex_init( &ad_undef_mutex );
   1168 	ldap_pvt_thread_mutex_init( &oc_undef_mutex );
   1169 
   1170 	for( i=0; ad_map[i].ssam_name; i++ ) {
   1171 		assert( ad_map[i].ssam_defn != NULL );
   1172 		{
   1173 			LDAPAttributeType *at;
   1174 			int		code;
   1175 			const char	*err;
   1176 
   1177 			at = ldap_str2attributetype( ad_map[i].ssam_defn,
   1178 				&code, &err, LDAP_SCHEMA_ALLOW_ALL );
   1179 			if ( !at ) {
   1180 				fprintf( stderr,
   1181 					"slap_schema_load: AttributeType \"%s\": %s before %s\n",
   1182 					 ad_map[i].ssam_name, ldap_scherr2str(code), err );
   1183 				return code;
   1184 			}
   1185 
   1186 			if ( at->at_oid == NULL ) {
   1187 				fprintf( stderr, "slap_schema_load: "
   1188 					"AttributeType \"%s\": no OID\n",
   1189 					ad_map[i].ssam_name );
   1190 				ldap_attributetype_free( at );
   1191 				return LDAP_OTHER;
   1192 			}
   1193 
   1194 			code = at_add( at, 0, NULL, NULL, &err );
   1195 			if ( code ) {
   1196 				ldap_attributetype_free( at );
   1197 				fprintf( stderr, "slap_schema_load: AttributeType "
   1198 					"\"%s\": %s: \"%s\"\n",
   1199 					 ad_map[i].ssam_name, scherr2str(code), err );
   1200 				return code;
   1201 			}
   1202 			ldap_memfree( at );
   1203 		}
   1204 		{
   1205 			int rc;
   1206 			const char *text;
   1207 			Syntax *syntax = NULL;
   1208 
   1209 			AttributeDescription ** adp = (AttributeDescription **)
   1210 				&(((char *) &slap_schema)[ad_map[i].ssam_offset]);
   1211 
   1212 			assert( *adp == NULL );
   1213 
   1214 			rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );
   1215 			if( rc != LDAP_SUCCESS ) {
   1216 				fprintf( stderr, "slap_schema_load: AttributeType \"%s\": "
   1217 					"not defined in schema\n",
   1218 					ad_map[i].ssam_name );
   1219 				return rc;
   1220 			}
   1221 
   1222 			if( ad_map[i].ssam_check ) {
   1223 				/* install check routine */
   1224 				(*adp)->ad_type->sat_check = ad_map[i].ssam_check;
   1225 			}
   1226 			/* install flags */
   1227 			(*adp)->ad_type->sat_flags |= ad_map[i].ssam_flags;
   1228 
   1229 			/* install custom syntax routines */
   1230 			if( ad_map[i].ssam_syn_validate ||
   1231 				ad_map[i].ssam_syn_pretty )
   1232 			{
   1233 				Syntax *syn;
   1234 
   1235 				syntax = (*adp)->ad_type->sat_syntax;
   1236 
   1237 				syn = ch_malloc( sizeof( Syntax ) );
   1238 				*syn = *syntax;
   1239 
   1240 				if( ad_map[i].ssam_syn_validate ) {
   1241 					syn->ssyn_validate = ad_map[i].ssam_syn_validate;
   1242 				}
   1243 				if( ad_map[i].ssam_syn_pretty ) {
   1244 					syn->ssyn_pretty = ad_map[i].ssam_syn_pretty;
   1245 				}
   1246 
   1247 				(*adp)->ad_type->sat_syntax = syn;
   1248 			}
   1249 
   1250 			/* install custom rule routines */
   1251 			if( syntax != NULL ||
   1252 				ad_map[i].ssam_mr_convert ||
   1253 				ad_map[i].ssam_mr_normalize ||
   1254 				ad_map[i].ssam_mr_match ||
   1255 				ad_map[i].ssam_mr_indexer ||
   1256 				ad_map[i].ssam_mr_filter )
   1257 			{
   1258 				MatchingRule *mr = ch_malloc( sizeof( MatchingRule ) );
   1259 				*mr = *(*adp)->ad_type->sat_equality;
   1260 
   1261 				if ( syntax != NULL ) {
   1262 					mr->smr_syntax = (*adp)->ad_type->sat_syntax;
   1263 				}
   1264 				if ( ad_map[i].ssam_mr_convert ) {
   1265 					mr->smr_convert = ad_map[i].ssam_mr_convert;
   1266 				}
   1267 				if ( ad_map[i].ssam_mr_normalize ) {
   1268 					mr->smr_normalize = ad_map[i].ssam_mr_normalize;
   1269 				}
   1270 				if ( ad_map[i].ssam_mr_match ) {
   1271 					mr->smr_match = ad_map[i].ssam_mr_match;
   1272 				}
   1273 				if ( ad_map[i].ssam_mr_indexer ) {
   1274 					mr->smr_indexer = ad_map[i].ssam_mr_indexer;
   1275 				}
   1276 				if ( ad_map[i].ssam_mr_filter ) {
   1277 					mr->smr_filter = ad_map[i].ssam_mr_filter;
   1278 				}
   1279 
   1280 				(*adp)->ad_type->sat_equality = mr;
   1281 			}
   1282 		}
   1283 	}
   1284 
   1285 	for( i=0; oc_map[i].ssom_name; i++ ) {
   1286 		assert( oc_map[i].ssom_defn != NULL );
   1287 		{
   1288 			LDAPObjectClass *oc;
   1289 			int		code;
   1290 			const char	*err;
   1291 
   1292 			oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
   1293 				LDAP_SCHEMA_ALLOW_ALL );
   1294 			if ( !oc ) {
   1295 				fprintf( stderr, "slap_schema_load: ObjectClass "
   1296 					"\"%s\": %s before %s\n",
   1297 				 	oc_map[i].ssom_name, ldap_scherr2str(code), err );
   1298 				return code;
   1299 			}
   1300 
   1301 			if ( oc->oc_oid == NULL ) {
   1302 				fprintf( stderr, "slap_schema_load: ObjectClass "
   1303 					"\"%s\": no OID\n",
   1304 					oc_map[i].ssom_name );
   1305 				ldap_objectclass_free( oc );
   1306 				return LDAP_OTHER;
   1307 			}
   1308 
   1309 			code = oc_add(oc,0,NULL,NULL,&err);
   1310 			if ( code ) {
   1311 				ldap_objectclass_free( oc );
   1312 				fprintf( stderr, "slap_schema_load: ObjectClass "
   1313 					"\"%s\": %s: \"%s\"\n",
   1314 				 	oc_map[i].ssom_name, scherr2str(code), err);
   1315 				return code;
   1316 			}
   1317 			ldap_memfree(oc);
   1318 
   1319 		}
   1320 		{
   1321 			ObjectClass ** ocp = (ObjectClass **)
   1322 				&(((char *) &slap_schema)[oc_map[i].ssom_offset]);
   1323 
   1324 			assert( *ocp == NULL );
   1325 
   1326 			*ocp = oc_find( oc_map[i].ssom_name );
   1327 			if( *ocp == NULL ) {
   1328 				fprintf( stderr, "slap_schema_load: "
   1329 					"ObjectClass \"%s\": not defined in schema\n",
   1330 					oc_map[i].ssom_name );
   1331 				return LDAP_OBJECT_CLASS_VIOLATION;
   1332 			}
   1333 
   1334 			if( oc_map[i].ssom_check ) {
   1335 				/* install check routine */
   1336 				(*ocp)->soc_check = oc_map[i].ssom_check;
   1337 			}
   1338 			/* install flags */
   1339 			(*ocp)->soc_flags |= oc_map[i].ssom_flags;
   1340 		}
   1341 	}
   1342 
   1343 	return LDAP_SUCCESS;
   1344 }
   1345 
   1346 int
   1347 slap_schema_check( void )
   1348 {
   1349 	/* we should only be called once after schema_init() was called */
   1350 	assert( schema_init_done == 1 );
   1351 
   1352 	/*
   1353 	 * cycle thru attributeTypes to build matchingRuleUse
   1354 	 */
   1355 	if ( matching_rule_use_init() ) {
   1356 		return LDAP_OTHER;
   1357 	}
   1358 
   1359 	++schema_init_done;
   1360 	return LDAP_SUCCESS;
   1361 }
   1362 
   1363 static int rootDseObjectClass (
   1364 	Backend *be,
   1365 	Entry *e,
   1366 	ObjectClass *oc,
   1367 	const char** text,
   1368 	char *textbuf, size_t textlen )
   1369 {
   1370 	*text = textbuf;
   1371 
   1372 	if( e->e_nname.bv_len ) {
   1373 		snprintf( textbuf, textlen,
   1374 			"objectClass \"%s\" only allowed in the root DSE",
   1375 			oc->soc_oid );
   1376 		return LDAP_OBJECT_CLASS_VIOLATION;
   1377 	}
   1378 
   1379 	/* we should not be called for the root DSE */
   1380 	assert( 0 );
   1381 	return LDAP_SUCCESS;
   1382 }
   1383 
   1384 static int aliasObjectClass (
   1385 	Backend *be,
   1386 	Entry *e,
   1387 	ObjectClass *oc,
   1388 	const char** text,
   1389 	char *textbuf, size_t textlen )
   1390 {
   1391 	*text = textbuf;
   1392 
   1393 	if( !SLAP_ALIASES(be) ) {
   1394 		snprintf( textbuf, textlen,
   1395 			"objectClass \"%s\" not supported in context",
   1396 			oc->soc_oid );
   1397 		return LDAP_OBJECT_CLASS_VIOLATION;
   1398 	}
   1399 
   1400 	return LDAP_SUCCESS;
   1401 }
   1402 
   1403 static int referralObjectClass (
   1404 	Backend *be,
   1405 	Entry *e,
   1406 	ObjectClass *oc,
   1407 	const char** text,
   1408 	char *textbuf, size_t textlen )
   1409 {
   1410 	*text = textbuf;
   1411 
   1412 	if( !SLAP_REFERRALS(be) ) {
   1413 		snprintf( textbuf, textlen,
   1414 			"objectClass \"%s\" not supported in context",
   1415 			oc->soc_oid );
   1416 		return LDAP_OBJECT_CLASS_VIOLATION;
   1417 	}
   1418 
   1419 	return LDAP_SUCCESS;
   1420 }
   1421 
   1422 static int subentryObjectClass (
   1423 	Backend *be,
   1424 	Entry *e,
   1425 	ObjectClass *oc,
   1426 	const char** text,
   1427 	char *textbuf, size_t textlen )
   1428 {
   1429 	*text = textbuf;
   1430 
   1431 	if( !SLAP_SUBENTRIES(be) ) {
   1432 		snprintf( textbuf, textlen,
   1433 			"objectClass \"%s\" not supported in context",
   1434 			oc->soc_oid );
   1435 		return LDAP_OBJECT_CLASS_VIOLATION;
   1436 	}
   1437 
   1438 	if( oc != slap_schema.si_oc_subentry && !is_entry_subentry( e ) ) {
   1439 		snprintf( textbuf, textlen,
   1440 			"objectClass \"%s\" only allowed in subentries",
   1441 			oc->soc_oid );
   1442 		return LDAP_OBJECT_CLASS_VIOLATION;
   1443 	}
   1444 
   1445 	return LDAP_SUCCESS;
   1446 }
   1447 
   1448 #ifdef LDAP_DYNAMIC_OBJECTS
   1449 static int dynamicObjectClass (
   1450 	Backend *be,
   1451 	Entry *e,
   1452 	ObjectClass *oc,
   1453 	const char** text,
   1454 	char *textbuf, size_t textlen )
   1455 {
   1456 	*text = textbuf;
   1457 
   1458 	if( !SLAP_DYNAMIC(be) ) {
   1459 		snprintf( textbuf, textlen,
   1460 			"objectClass \"%s\" not supported in context",
   1461 			oc->soc_oid );
   1462 		return LDAP_OBJECT_CLASS_VIOLATION;
   1463 	}
   1464 
   1465 	return LDAP_SUCCESS;
   1466 }
   1467 #endif /* LDAP_DYNAMIC_OBJECTS */
   1468 
   1469 static int rootDseAttribute (
   1470 	Backend *be,
   1471 	Entry *e,
   1472 	Attribute *attr,
   1473 	const char** text,
   1474 	char *textbuf, size_t textlen )
   1475 {
   1476 	*text = textbuf;
   1477 
   1478 	if( e->e_nname.bv_len ) {
   1479 		snprintf( textbuf, textlen,
   1480 			"attribute \"%s\" only allowed in the root DSE",
   1481 			attr->a_desc->ad_cname.bv_val );
   1482 		return LDAP_OBJECT_CLASS_VIOLATION;
   1483 	}
   1484 
   1485 	/* we should not be called for the root DSE */
   1486 	assert( 0 );
   1487 	return LDAP_SUCCESS;
   1488 }
   1489 
   1490 static int aliasAttribute (
   1491 	Backend *be,
   1492 	Entry *e,
   1493 	Attribute *attr,
   1494 	const char** text,
   1495 	char *textbuf, size_t textlen )
   1496 {
   1497 	*text = textbuf;
   1498 
   1499 	if( !SLAP_ALIASES(be) ) {
   1500 		snprintf( textbuf, textlen,
   1501 			"attribute \"%s\" not supported in context",
   1502 			attr->a_desc->ad_cname.bv_val );
   1503 		return LDAP_OBJECT_CLASS_VIOLATION;
   1504 	}
   1505 
   1506 	if( !is_entry_alias( e ) ) {
   1507 		snprintf( textbuf, textlen,
   1508 			"attribute \"%s\" only allowed in the alias",
   1509 			attr->a_desc->ad_cname.bv_val );
   1510 		return LDAP_OBJECT_CLASS_VIOLATION;
   1511 	}
   1512 
   1513 	return LDAP_SUCCESS;
   1514 }
   1515 
   1516 static int referralAttribute (
   1517 	Backend *be,
   1518 	Entry *e,
   1519 	Attribute *attr,
   1520 	const char** text,
   1521 	char *textbuf, size_t textlen )
   1522 {
   1523 	*text = textbuf;
   1524 
   1525 	if( !SLAP_REFERRALS(be) ) {
   1526 		snprintf( textbuf, textlen,
   1527 			"attribute \"%s\" not supported in context",
   1528 			attr->a_desc->ad_cname.bv_val );
   1529 		return LDAP_OBJECT_CLASS_VIOLATION;
   1530 	}
   1531 
   1532 	if( !is_entry_referral( e ) ) {
   1533 		snprintf( textbuf, textlen,
   1534 			"attribute \"%s\" only allowed in the referral",
   1535 			attr->a_desc->ad_cname.bv_val );
   1536 		return LDAP_OBJECT_CLASS_VIOLATION;
   1537 	}
   1538 
   1539 	return LDAP_SUCCESS;
   1540 }
   1541 
   1542 static int subentryAttribute (
   1543 	Backend *be,
   1544 	Entry *e,
   1545 	Attribute *attr,
   1546 	const char** text,
   1547 	char *textbuf, size_t textlen )
   1548 {
   1549 	*text = textbuf;
   1550 
   1551 	if( !SLAP_SUBENTRIES(be) ) {
   1552 		snprintf( textbuf, textlen,
   1553 			"attribute \"%s\" not supported in context",
   1554 			attr->a_desc->ad_cname.bv_val );
   1555 		return LDAP_OBJECT_CLASS_VIOLATION;
   1556 	}
   1557 
   1558 	if( !is_entry_subentry( e ) ) {
   1559 		snprintf( textbuf, textlen,
   1560 			"attribute \"%s\" only allowed in the subentry",
   1561 			attr->a_desc->ad_cname.bv_val );
   1562 		return LDAP_OBJECT_CLASS_VIOLATION;
   1563 	}
   1564 
   1565 	return LDAP_SUCCESS;
   1566 }
   1567 
   1568 static int administrativeRoleAttribute (
   1569 	Backend *be,
   1570 	Entry *e,
   1571 	Attribute *attr,
   1572 	const char** text,
   1573 	char *textbuf, size_t textlen )
   1574 {
   1575 	*text = textbuf;
   1576 
   1577 	if( !SLAP_SUBENTRIES(be) ) {
   1578 		snprintf( textbuf, textlen,
   1579 			"attribute \"%s\" not supported in context",
   1580 			attr->a_desc->ad_cname.bv_val );
   1581 		return LDAP_OBJECT_CLASS_VIOLATION;
   1582 	}
   1583 
   1584 	snprintf( textbuf, textlen,
   1585 		"attribute \"%s\" not supported!",
   1586 		attr->a_desc->ad_cname.bv_val );
   1587 	return LDAP_OBJECT_CLASS_VIOLATION;
   1588 }
   1589 
   1590 #ifdef LDAP_DYNAMIC_OBJECTS
   1591 static int dynamicAttribute (
   1592 	Backend *be,
   1593 	Entry *e,
   1594 	Attribute *attr,
   1595 	const char** text,
   1596 	char *textbuf, size_t textlen )
   1597 {
   1598 	*text = textbuf;
   1599 
   1600 	if( !SLAP_DYNAMIC(be) ) {
   1601 		snprintf( textbuf, textlen,
   1602 			"attribute \"%s\" not supported in context",
   1603 			attr->a_desc->ad_cname.bv_val );
   1604 		return LDAP_OBJECT_CLASS_VIOLATION;
   1605 	}
   1606 
   1607 	if( !is_entry_dynamicObject( e ) ) {
   1608 		snprintf( textbuf, textlen,
   1609 			"attribute \"%s\" only allowed in dynamic object",
   1610 			attr->a_desc->ad_cname.bv_val );
   1611 		return LDAP_OBJECT_CLASS_VIOLATION;
   1612 	}
   1613 
   1614 	return LDAP_SUCCESS;
   1615 }
   1616 #endif /* LDAP_DYNAMIC_OBJECTS */
   1617