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