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