Home | History | Annotate | Line # | Download | only in slapd
schema_prep.c revision 1.1.1.6
      1 /*	$NetBSD: schema_prep.c,v 1.1.1.6 2017/02/09 01:46: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-2016 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.1.1.6 2017/02/09 01:46: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, SLAP_AT_HIDE,
    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, SLAP_AT_HIDE,
    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 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )",
    642 		rootDseAttribute, 0,
    643 		NULL, NULL,
    644 		NULL, NULL, NULL, NULL, NULL,
    645 		offsetof(struct slap_internal_schema, si_ad_namingContexts) },
    646 	{ "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
    647 			"NAME 'supportedControl' "
    648 			"DESC 'RFC4512: supported controls' "
    649 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
    650 		rootDseAttribute, 0,
    651 		NULL, NULL,
    652 		NULL, NULL, NULL, NULL, NULL,
    653 		offsetof(struct slap_internal_schema, si_ad_supportedControl) },
    654 	{ "supportedExtension", "( 1.3.6.1.4.1.1466.101.120.7 "
    655 			"NAME 'supportedExtension' "
    656 			"DESC 'RFC4512: supported extended operations' "
    657 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
    658 		rootDseAttribute, 0,
    659 		NULL, NULL,
    660 		NULL, NULL, NULL, NULL, NULL,
    661 		offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
    662 	{ "supportedLDAPVersion", "( 1.3.6.1.4.1.1466.101.120.15 "
    663 			"NAME 'supportedLDAPVersion' "
    664 			"DESC 'RFC4512: supported LDAP versions' "
    665 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )",
    666 		rootDseAttribute, 0,
    667 		NULL, NULL,
    668 		NULL, NULL, NULL, NULL, NULL,
    669 		offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
    670 	{ "supportedSASLMechanisms", "( 1.3.6.1.4.1.1466.101.120.14 "
    671 			"NAME 'supportedSASLMechanisms' "
    672 			"DESC 'RFC4512: supported SASL mechanisms'"
    673 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )",
    674 		rootDseAttribute, 0,
    675 		NULL, NULL,
    676 		NULL, NULL, NULL, NULL, NULL,
    677 		offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
    678 	{ "supportedFeatures", "( 1.3.6.1.4.1.4203.1.3.5 "
    679 			"NAME 'supportedFeatures' "
    680 			"DESC 'RFC4512: features supported by the server' "
    681 			"EQUALITY objectIdentifierMatch "
    682 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
    683 			"USAGE dSAOperation )",
    684 		rootDseAttribute, 0,
    685 		NULL, NULL,
    686 		NULL, NULL, NULL, NULL, NULL,
    687 		offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
    688 	{ "monitorContext", "( 1.3.6.1.4.1.4203.666.1.10 "
    689 			"NAME 'monitorContext' "
    690 			"DESC 'monitor context' "
    691 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    692 			"EQUALITY distinguishedNameMatch "
    693 			"SINGLE-VALUE NO-USER-MODIFICATION "
    694 			"USAGE dSAOperation )",
    695 		rootDseAttribute, SLAP_AT_HIDE,
    696 		NULL, NULL,
    697 		NULL, NULL, NULL, NULL, NULL,
    698 		offsetof(struct slap_internal_schema, si_ad_monitorContext) },
    699 	{ "configContext", "( 1.3.6.1.4.1.4203.1.12.2.1 "
    700 			"NAME 'configContext' "
    701 			"DESC 'config context' "
    702 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
    703 			"EQUALITY distinguishedNameMatch "
    704 			"SINGLE-VALUE NO-USER-MODIFICATION "
    705 			"USAGE dSAOperation )",
    706 		rootDseAttribute, SLAP_AT_HIDE,
    707 		NULL, NULL,
    708 		NULL, NULL, NULL, NULL, NULL,
    709 		offsetof(struct slap_internal_schema, si_ad_configContext) },
    710 	{ "vendorName", "( 1.3.6.1.1.4 NAME 'vendorName' "
    711 			"DESC 'RFC3045: name of implementation vendor' "
    712 			"EQUALITY caseExactMatch "
    713 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
    714 			"SINGLE-VALUE NO-USER-MODIFICATION "
    715 			"USAGE dSAOperation )",
    716 		rootDseAttribute, 0,
    717 		NULL, NULL,
    718 		NULL, NULL, NULL, NULL, NULL,
    719 		offsetof(struct slap_internal_schema, si_ad_vendorName) },
    720 	{ "vendorVersion", "( 1.3.6.1.1.5 NAME 'vendorVersion' "
    721 			"DESC 'RFC3045: version of implementation' "
    722 			"EQUALITY caseExactMatch "
    723 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
    724 			"SINGLE-VALUE NO-USER-MODIFICATION "
    725 			"USAGE dSAOperation )",
    726 		rootDseAttribute, 0,
    727 		NULL, NULL,
    728 		NULL, NULL, NULL, NULL, NULL,
    729 		offsetof(struct slap_internal_schema, si_ad_vendorVersion) },
    730 
    731 	/* subentry attributes */
    732 	{ "administrativeRole", "( 2.5.18.5 NAME 'administrativeRole' "
    733 			"DESC 'RFC3672: administrative role' "
    734 			"EQUALITY objectIdentifierMatch "
    735 			"USAGE directoryOperation "
    736 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
    737 		administrativeRoleAttribute, SLAP_AT_HIDE,
    738 		NULL, NULL,
    739 		NULL, NULL, NULL, NULL, NULL,
    740 		offsetof(struct slap_internal_schema, si_ad_administrativeRole) },
    741 	{ "subtreeSpecification", "( 2.5.18.6 NAME 'subtreeSpecification' "
    742 			"DESC 'RFC3672: subtree specification' "
    743 			"SINGLE-VALUE "
    744 			"USAGE directoryOperation "
    745 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.45 )",
    746 		subentryAttribute, SLAP_AT_HIDE,
    747 		NULL, NULL,
    748 		NULL, NULL, NULL, NULL, NULL,
    749 		offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
    750 
    751 	/* subschema subentry attributes */
    752 	{ "dITStructureRules", "( 2.5.21.1 NAME 'dITStructureRules' "
    753 			"DESC 'RFC4512: DIT structure rules' "
    754 			"EQUALITY integerFirstComponentMatch "
    755 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 "
    756 			"USAGE directoryOperation ) ",
    757 		subentryAttribute, SLAP_AT_HIDE,
    758 		NULL, NULL,
    759 		NULL, NULL, NULL, NULL, NULL,
    760 		offsetof(struct slap_internal_schema, si_ad_ditStructureRules) },
    761 	{ "dITContentRules", "( 2.5.21.2 NAME 'dITContentRules' "
    762 			"DESC 'RFC4512: DIT content rules' "
    763 			"EQUALITY objectIdentifierFirstComponentMatch "
    764 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )",
    765 		subentryAttribute, SLAP_AT_HIDE,
    766 		oidValidate, NULL,
    767 		NULL, NULL, objectClassMatch, NULL, NULL,
    768 		offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
    769 	{ "matchingRules", "( 2.5.21.4 NAME 'matchingRules' "
    770 			"DESC 'RFC4512: matching rules' "
    771 			"EQUALITY objectIdentifierFirstComponentMatch "
    772 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )",
    773 		subentryAttribute, 0,
    774 		oidValidate, NULL,
    775 		NULL, NULL, matchingRuleMatch, NULL, NULL,
    776 		offsetof(struct slap_internal_schema, si_ad_matchingRules) },
    777 	{ "attributeTypes", "( 2.5.21.5 NAME 'attributeTypes' "
    778 			"DESC 'RFC4512: attribute types' "
    779 			"EQUALITY objectIdentifierFirstComponentMatch "
    780 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )",
    781 		subentryAttribute, 0,
    782 		oidValidate, NULL,
    783 		NULL, NULL, attributeTypeMatch, NULL, NULL,
    784 		offsetof(struct slap_internal_schema, si_ad_attributeTypes) },
    785 	{ "objectClasses", "( 2.5.21.6 NAME 'objectClasses' "
    786 			"DESC 'RFC4512: object classes' "
    787 			"EQUALITY objectIdentifierFirstComponentMatch "
    788 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )",
    789 		subentryAttribute, 0,
    790 		oidValidate, NULL,
    791 		NULL, NULL, objectClassMatch, NULL, NULL,
    792 		offsetof(struct slap_internal_schema, si_ad_objectClasses) },
    793 	{ "nameForms", "( 2.5.21.7 NAME 'nameForms' "
    794 			"DESC 'RFC4512: name forms ' "
    795 			"EQUALITY objectIdentifierFirstComponentMatch "
    796 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )",
    797 		subentryAttribute, SLAP_AT_HIDE,
    798 		NULL, NULL,
    799 		NULL, NULL, NULL, NULL, NULL,
    800 		offsetof(struct slap_internal_schema, si_ad_nameForms) },
    801 	{ "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
    802 			"DESC 'RFC4512: matching rule uses' "
    803 			"EQUALITY objectIdentifierFirstComponentMatch "
    804 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
    805 		subentryAttribute, 0,
    806 		oidValidate, NULL,
    807 		NULL, NULL, matchingRuleMatch, NULL, NULL,
    808 		offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
    809 
    810 	{ "ldapSyntaxes", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' "
    811 			"DESC 'RFC4512: LDAP syntaxes' "
    812 			"EQUALITY objectIdentifierFirstComponentMatch "
    813 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )",
    814 		subentryAttribute, 0,
    815 		NULL, NULL,
    816 		NULL, NULL, NULL, NULL, NULL,
    817 		offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },
    818 
    819 	/* knowledge information */
    820 	{ "aliasedObjectName", "( 2.5.4.1 "
    821 			"NAME ( 'aliasedObjectName' 'aliasedEntryName' ) "
    822 			"DESC 'RFC4512: name of aliased object' "
    823 			"EQUALITY distinguishedNameMatch "
    824 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
    825 		aliasAttribute, SLAP_AT_FINAL,
    826 		NULL, NULL,
    827 		NULL, NULL, NULL, NULL, NULL,
    828 		offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
    829 	{ "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
    830 			"DESC 'RFC3296: subordinate referral URL' "
    831 			"EQUALITY caseExactMatch "
    832 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
    833 			"USAGE distributedOperation )",
    834 		referralAttribute, 0,
    835 		NULL, NULL,
    836 		NULL, NULL, NULL, NULL, NULL,
    837 		offsetof(struct slap_internal_schema, si_ad_ref) },
    838 
    839 	/* access control internals */
    840 	{ "entry", "( 1.3.6.1.4.1.4203.1.3.1 "
    841 			"NAME 'entry' "
    842 			"DESC 'OpenLDAP ACL entry pseudo-attribute' "
    843 			"SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
    844 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
    845 		NULL, SLAP_AT_HIDE,
    846 		NULL, NULL,
    847 		NULL, NULL, NULL, NULL, NULL,
    848 		offsetof(struct slap_internal_schema, si_ad_entry) },
    849 	{ "children", "( 1.3.6.1.4.1.4203.1.3.2 "
    850 			"NAME 'children' "
    851 			"DESC 'OpenLDAP ACL children pseudo-attribute' "
    852 			"SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
    853 			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
    854 		NULL, SLAP_AT_HIDE,
    855 		NULL, NULL,
    856 		NULL, NULL, NULL, NULL, NULL,
    857 		offsetof(struct slap_internal_schema, si_ad_children) },
    858 
    859 	/* access control externals */
    860 	{ "authzTo", "( 1.3.6.1.4.1.4203.666.1.8 "
    861 			"NAME ( 'authzTo' 'saslAuthzTo' ) "
    862 			"DESC 'proxy authorization targets' "
    863 			"EQUALITY authzMatch "
    864 			"SYNTAX 1.3.6.1.4.1.4203.666.2.7 "
    865 			"X-ORDERED 'VALUES' "
    866 			"USAGE distributedOperation )",
    867 		NULL, SLAP_AT_HIDE,
    868 		NULL, NULL,
    869 		NULL, NULL, NULL, NULL, NULL,
    870 		offsetof(struct slap_internal_schema, si_ad_saslAuthzTo) },
    871 	{ "authzFrom", "( 1.3.6.1.4.1.4203.666.1.9 "
    872 			"NAME ( 'authzFrom' 'saslAuthzFrom' ) "
    873 			"DESC 'proxy authorization sources' "
    874 			"EQUALITY authzMatch "
    875 			"SYNTAX 1.3.6.1.4.1.4203.666.2.7 "
    876 			"X-ORDERED 'VALUES' "
    877 			"USAGE distributedOperation )",
    878 		NULL, SLAP_AT_HIDE,
    879 		NULL, NULL,
    880 		NULL, NULL, NULL, NULL, NULL,
    881 		offsetof(struct slap_internal_schema, si_ad_saslAuthzFrom) },
    882 
    883 #ifdef LDAP_DYNAMIC_OBJECTS
    884 	{ "entryTtl", "( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl' "
    885 			"DESC 'RFC2589: entry time-to-live' "
    886 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE "
    887 			"NO-USER-MODIFICATION USAGE dSAOperation )",
    888 		dynamicAttribute, SLAP_AT_MANAGEABLE,
    889 		NULL, NULL,
    890 		NULL, NULL, NULL, NULL, NULL,
    891 		offsetof(struct slap_internal_schema, si_ad_entryTtl) },
    892 	{ "dynamicSubtrees", "( 1.3.6.1.4.1.1466.101.119.4 "
    893 			"NAME 'dynamicSubtrees' "
    894 			"DESC 'RFC2589: dynamic subtrees' "
    895 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
    896 			"USAGE dSAOperation )",
    897 		rootDseAttribute, 0,
    898 		NULL, NULL,
    899 		NULL, NULL, NULL, NULL, NULL,
    900 		offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },
    901 #endif
    902 
    903 	/* userApplication attributes (which system schema depends upon) */
    904 	{ "distinguishedName", "( 2.5.4.49 NAME 'distinguishedName' "
    905 			"DESC 'RFC4519: common supertype of DN attributes' "
    906 			"EQUALITY distinguishedNameMatch "
    907 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
    908 		NULL, SLAP_AT_ABSTRACT,
    909 		NULL, NULL,
    910 		NULL, NULL, NULL, NULL, NULL,
    911 		offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
    912 	{ "name", "( 2.5.4.41 NAME 'name' "
    913 			"DESC 'RFC4519: common supertype of name attributes' "
    914 			"EQUALITY caseIgnoreMatch "
    915 			"SUBSTR caseIgnoreSubstringsMatch "
    916 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )",
    917 		NULL, SLAP_AT_ABSTRACT,
    918 		NULL, NULL,
    919 		NULL, NULL, NULL, NULL, NULL,
    920 		offsetof(struct slap_internal_schema, si_ad_name) },
    921 	{ "cn", "( 2.5.4.3 NAME ( 'cn' 'commonName' ) "
    922 			"DESC 'RFC4519: common name(s) for which the entity is known by' "
    923 			"SUP name )",
    924 		NULL, 0,
    925 		NULL, NULL,
    926 		NULL, NULL, NULL, NULL, NULL,
    927 		offsetof(struct slap_internal_schema, si_ad_cn) },
    928 	{ "uid", "( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' ) "
    929 			"DESC 'RFC4519: user identifier' "
    930 			"EQUALITY caseIgnoreMatch "
    931 			"SUBSTR caseIgnoreSubstringsMatch "
    932 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )",
    933 		NULL, 0,
    934 		NULL, NULL,
    935 		NULL, NULL, NULL, NULL, NULL,
    936 		offsetof(struct slap_internal_schema, si_ad_uid) },
    937 	{ "uidNumber", /* for ldapi:// */
    938 		"( 1.3.6.1.1.1.1.0 NAME 'uidNumber' "
    939     		"DESC 'RFC2307: An integer uniquely identifying a user "
    940 				"in an administrative domain' "
    941     		"EQUALITY integerMatch "
    942     		"ORDERING integerOrderingMatch "
    943     		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )",
    944 		NULL, 0,
    945 		NULL, NULL,
    946 		NULL, NULL, NULL, NULL, NULL,
    947 		offsetof(struct slap_internal_schema, si_ad_uidNumber) },
    948 	{ "gidNumber", /* for ldapi:// */
    949 		"( 1.3.6.1.1.1.1.1 NAME 'gidNumber' "
    950     		"DESC 'RFC2307: An integer uniquely identifying a group "
    951 				"in an administrative domain' "
    952     		"EQUALITY integerMatch "
    953     		"ORDERING integerOrderingMatch "
    954     		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )",
    955 		NULL, 0,
    956 		NULL, NULL,
    957 		NULL, NULL, NULL, NULL, NULL,
    958 		offsetof(struct slap_internal_schema, si_ad_gidNumber) },
    959 	{ "userPassword", "( 2.5.4.35 NAME 'userPassword' "
    960 			"DESC 'RFC4519/2307: password of user' "
    961 			"EQUALITY octetStringMatch "
    962 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )",
    963 		NULL, 0,
    964 		NULL, NULL,
    965 		NULL, NULL, NULL, NULL, NULL,
    966 		offsetof(struct slap_internal_schema, si_ad_userPassword) },
    967 
    968 	{ "labeledURI", "( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI' "
    969 			"DESC 'RFC2079: Uniform Resource Identifier with optional label' "
    970 			"EQUALITY caseExactMatch "
    971 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
    972 		NULL, 0,
    973 		NULL, NULL,
    974 		NULL, NULL, NULL, NULL, NULL,
    975 		offsetof(struct slap_internal_schema, si_ad_labeledURI) },
    976 
    977 #ifdef SLAPD_AUTHPASSWD
    978 	{ "authPassword", "( 1.3.6.1.4.1.4203.1.3.4 "
    979 			"NAME 'authPassword' "
    980 			"DESC 'RFC3112: authentication password attribute' "
    981 			"EQUALITY 1.3.6.1.4.1.4203.1.2.2 "
    982 			"SYNTAX 1.3.6.1.4.1.4203.1.1.2 )",
    983 		NULL, 0,
    984 		NULL, NULL,
    985 		NULL, NULL, NULL, NULL, NULL,
    986 		offsetof(struct slap_internal_schema, si_ad_authPassword) },
    987 	{ "supportedAuthPasswordSchemes", "( 1.3.6.1.4.1.4203.1.3.3 "
    988 			"NAME 'supportedAuthPasswordSchemes' "
    989 			"DESC 'RFC3112: supported authPassword schemes' "
    990 			"EQUALITY caseExactIA5Match "
    991 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} "
    992 			"USAGE dSAOperation )",
    993 		subschemaAttribute, 0,
    994 		NULL, NULL,
    995 		NULL, NULL, NULL, NULL, NULL,
    996 		offsetof(struct slap_internal_schema, si_ad_authPasswordSchemes) },
    997 #endif
    998 
    999 	{ "description", "( 2.5.4.13 NAME 'description' "
   1000 			"DESC 'RFC4519: descriptive information' "
   1001 			"EQUALITY caseIgnoreMatch "
   1002 			"SUBSTR caseIgnoreSubstringsMatch "
   1003 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )",
   1004 		NULL, 0,
   1005 		NULL, NULL,
   1006 		NULL, NULL, NULL, NULL, NULL,
   1007 		offsetof(struct slap_internal_schema, si_ad_description) },
   1008 
   1009 	{ "seeAlso", "( 2.5.4.34 NAME 'seeAlso' "
   1010 			"DESC 'RFC4519: DN of related object' "
   1011 			"SUP distinguishedName )",
   1012 		NULL, 0,
   1013 		NULL, NULL,
   1014 		NULL, NULL, NULL, NULL, NULL,
   1015 		offsetof(struct slap_internal_schema, si_ad_seeAlso) },
   1016 
   1017 	{ NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 }
   1018 };
   1019 
   1020 static AttributeType slap_at_undefined = {
   1021 	{ "1.1.1", NULL, "Catchall for undefined attribute types", 1, NULL,
   1022 		NULL, NULL, NULL, NULL,
   1023 		0, 0, 0, 1, LDAP_SCHEMA_DSA_OPERATION, NULL }, /* LDAPAttributeType */
   1024 	BER_BVC("UNDEFINED"), /* cname */
   1025 	NULL, /* sup */
   1026 	NULL, /* subtypes */
   1027 	NULL, NULL, NULL, NULL,	/* matching rules routines */
   1028 	NULL, /* syntax (will be set later to "octetString") */
   1029 	NULL, /* schema check function */
   1030 	NULL, /* oidmacro */
   1031 	NULL, /* soidmacro */
   1032 	SLAP_AT_ABSTRACT|SLAP_AT_FINAL,	/* mask */
   1033 	{ NULL }, /* next */
   1034 	NULL /* attribute description */
   1035 	/* mutex (don't know how to initialize it :) */
   1036 };
   1037 
   1038 static AttributeType slap_at_proxied = {
   1039 	{ "1.1.1", NULL, "Catchall for undefined proxied attribute types", 1, NULL,
   1040 		NULL, NULL, NULL, NULL,
   1041 		0, 0, 0, 0, LDAP_SCHEMA_USER_APPLICATIONS, NULL }, /* LDAPAttributeType */
   1042 	BER_BVC("PROXIED"), /* cname */
   1043 	NULL, /* sup */
   1044 	NULL, /* subtypes */
   1045 	NULL, NULL, NULL, NULL,	/* matching rules routines (will be set later) */
   1046 	NULL, /* syntax (will be set later to "octetString") */
   1047 	NULL, /* schema check function */
   1048 	NULL, /* oidmacro */
   1049 	NULL, /* soidmacro */
   1050 	SLAP_AT_ABSTRACT|SLAP_AT_FINAL,	/* mask */
   1051 	{ NULL }, /* next */
   1052 	NULL /* attribute description */
   1053 	/* mutex (don't know how to initialize it :) */
   1054 };
   1055 
   1056 static struct slap_schema_mr_map {
   1057 	char *ssmm_name;
   1058 	size_t ssmm_offset;
   1059 } mr_map[] = {
   1060 	{ "caseExactIA5Match",
   1061 		offsetof(struct slap_internal_schema, si_mr_caseExactIA5Match) },
   1062 	{ "caseExactMatch",
   1063 		offsetof(struct slap_internal_schema, si_mr_caseExactMatch) },
   1064 	{ "caseExactSubstringsMatch",
   1065 		offsetof(struct slap_internal_schema, si_mr_caseExactSubstringsMatch) },
   1066 	{ "distinguishedNameMatch",
   1067 		offsetof(struct slap_internal_schema, si_mr_distinguishedNameMatch) },
   1068 	{ "dnSubtreeMatch",
   1069 		offsetof(struct slap_internal_schema, si_mr_dnSubtreeMatch) },
   1070 	{ "dnOneLevelMatch",
   1071 		offsetof(struct slap_internal_schema, si_mr_dnOneLevelMatch) },
   1072 	{ "dnSubordinateMatch",
   1073 		offsetof(struct slap_internal_schema, si_mr_dnSubordinateMatch) },
   1074 	{ "dnSuperiorMatch",
   1075 		offsetof(struct slap_internal_schema, si_mr_dnSuperiorMatch) },
   1076 	{ "integerMatch",
   1077 		offsetof(struct slap_internal_schema, si_mr_integerMatch) },
   1078 	{ "integerFirstComponentMatch",
   1079 		offsetof(struct slap_internal_schema,
   1080 			si_mr_integerFirstComponentMatch) },
   1081 	{ "objectIdentifierFirstComponentMatch",
   1082 		offsetof(struct slap_internal_schema,
   1083 			si_mr_objectIdentifierFirstComponentMatch) },
   1084 	{ "caseIgnoreMatch",
   1085 		offsetof(struct slap_internal_schema, si_mr_caseIgnoreMatch) },
   1086 	{ "caseIgnoreListMatch",
   1087 		offsetof(struct slap_internal_schema, si_mr_caseIgnoreListMatch) },
   1088 	{ NULL, 0 }
   1089 };
   1090 
   1091 static struct slap_schema_syn_map {
   1092 	char *sssm_name;
   1093 	size_t sssm_offset;
   1094 } syn_map[] = {
   1095 	{ "1.3.6.1.4.1.1466.115.121.1.15",
   1096 		offsetof(struct slap_internal_schema, si_syn_directoryString) },
   1097 	{ "1.3.6.1.4.1.1466.115.121.1.12",
   1098 		offsetof(struct slap_internal_schema, si_syn_distinguishedName) },
   1099 	{ "1.3.6.1.4.1.1466.115.121.1.27",
   1100 		offsetof(struct slap_internal_schema, si_syn_integer) },
   1101 	{ "1.3.6.1.4.1.1466.115.121.1.40",
   1102 		offsetof(struct slap_internal_schema, si_syn_octetString) },
   1103 	{ "1.3.6.1.4.1.1466.115.121.1.3",
   1104 		offsetof(struct slap_internal_schema, si_syn_attributeTypeDesc) },
   1105 	{ "1.3.6.1.4.1.1466.115.121.1.16",
   1106 		offsetof(struct slap_internal_schema, si_syn_ditContentRuleDesc) },
   1107 	{ "1.3.6.1.4.1.1466.115.121.1.54",
   1108 		offsetof(struct slap_internal_schema, si_syn_ldapSyntaxDesc) },
   1109 	{ "1.3.6.1.4.1.1466.115.121.1.30",
   1110 		offsetof(struct slap_internal_schema, si_syn_matchingRuleDesc) },
   1111 	{ "1.3.6.1.4.1.1466.115.121.1.31",
   1112 		offsetof(struct slap_internal_schema, si_syn_matchingRuleUseDesc) },
   1113 	{ "1.3.6.1.4.1.1466.115.121.1.35",
   1114 		offsetof(struct slap_internal_schema, si_syn_nameFormDesc) },
   1115 	{ "1.3.6.1.4.1.1466.115.121.1.37",
   1116 		offsetof(struct slap_internal_schema, si_syn_objectClassDesc) },
   1117 	{ "1.3.6.1.4.1.1466.115.121.1.17",
   1118 		offsetof(struct slap_internal_schema, si_syn_ditStructureRuleDesc) },
   1119 	{ NULL, 0 }
   1120 };
   1121 
   1122 int
   1123 slap_schema_load( void )
   1124 {
   1125 	int i;
   1126 
   1127 	for( i=0; syn_map[i].sssm_name; i++ ) {
   1128 		Syntax ** synp = (Syntax **)
   1129 			&(((char *) &slap_schema)[syn_map[i].sssm_offset]);
   1130 
   1131 		assert( *synp == NULL );
   1132 
   1133 		*synp = syn_find( syn_map[i].sssm_name );
   1134 
   1135 		if( *synp == NULL ) {
   1136 			fprintf( stderr, "slap_schema_load: Syntax: "
   1137 				"No syntax \"%s\" defined in schema\n",
   1138 				syn_map[i].sssm_name );
   1139 			return LDAP_INVALID_SYNTAX;
   1140 		}
   1141 	}
   1142 
   1143 	for( i=0; mr_map[i].ssmm_name; i++ ) {
   1144 		MatchingRule ** mrp = (MatchingRule **)
   1145 			&(((char *) &slap_schema)[mr_map[i].ssmm_offset]);
   1146 
   1147 		assert( *mrp == NULL );
   1148 
   1149 		*mrp = mr_find( mr_map[i].ssmm_name );
   1150 
   1151 		if( *mrp == NULL ) {
   1152 			fprintf( stderr, "slap_schema_load: MatchingRule: "
   1153 				"No matching rule \"%s\" defined in schema\n",
   1154 				mr_map[i].ssmm_name );
   1155 			return LDAP_INAPPROPRIATE_MATCHING;
   1156 		}
   1157 	}
   1158 
   1159 	slap_at_undefined.sat_syntax = slap_schema.si_syn_octetString;
   1160 	slap_schema.si_at_undefined = &slap_at_undefined;
   1161 
   1162 	slap_at_proxied.sat_equality = mr_find( "octetStringMatch" );
   1163 	slap_at_proxied.sat_approx = mr_find( "octetStringMatch" );
   1164 	slap_at_proxied.sat_ordering = mr_find( "octetStringOrderingMatch" );
   1165 	slap_at_proxied.sat_substr = mr_find( "octetStringSubstringsMatch" );
   1166 	slap_at_proxied.sat_syntax = slap_schema.si_syn_octetString;
   1167 	slap_schema.si_at_proxied = &slap_at_proxied;
   1168 
   1169 	ldap_pvt_thread_mutex_init( &ad_index_mutex );
   1170 	ldap_pvt_thread_mutex_init( &ad_undef_mutex );
   1171 	ldap_pvt_thread_mutex_init( &oc_undef_mutex );
   1172 
   1173 	for( i=0; ad_map[i].ssam_name; i++ ) {
   1174 		assert( ad_map[i].ssam_defn != NULL );
   1175 		{
   1176 			LDAPAttributeType *at;
   1177 			int		code;
   1178 			const char	*err;
   1179 
   1180 			at = ldap_str2attributetype( ad_map[i].ssam_defn,
   1181 				&code, &err, LDAP_SCHEMA_ALLOW_ALL );
   1182 			if ( !at ) {
   1183 				fprintf( stderr,
   1184 					"slap_schema_load: AttributeType \"%s\": %s before %s\n",
   1185 					 ad_map[i].ssam_name, ldap_scherr2str(code), err );
   1186 				return code;
   1187 			}
   1188 
   1189 			if ( at->at_oid == NULL ) {
   1190 				fprintf( stderr, "slap_schema_load: "
   1191 					"AttributeType \"%s\": no OID\n",
   1192 					ad_map[i].ssam_name );
   1193 				ldap_attributetype_free( at );
   1194 				return LDAP_OTHER;
   1195 			}
   1196 
   1197 			code = at_add( at, 0, NULL, NULL, &err );
   1198 			if ( code ) {
   1199 				ldap_attributetype_free( at );
   1200 				fprintf( stderr, "slap_schema_load: AttributeType "
   1201 					"\"%s\": %s: \"%s\"\n",
   1202 					 ad_map[i].ssam_name, scherr2str(code), err );
   1203 				return code;
   1204 			}
   1205 			ldap_memfree( at );
   1206 		}
   1207 		{
   1208 			int rc;
   1209 			const char *text;
   1210 			Syntax *syntax = NULL;
   1211 
   1212 			AttributeDescription ** adp = (AttributeDescription **)
   1213 				&(((char *) &slap_schema)[ad_map[i].ssam_offset]);
   1214 
   1215 			assert( *adp == NULL );
   1216 
   1217 			rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );
   1218 			if( rc != LDAP_SUCCESS ) {
   1219 				fprintf( stderr, "slap_schema_load: AttributeType \"%s\": "
   1220 					"not defined in schema\n",
   1221 					ad_map[i].ssam_name );
   1222 				return rc;
   1223 			}
   1224 
   1225 			if( ad_map[i].ssam_check ) {
   1226 				/* install check routine */
   1227 				(*adp)->ad_type->sat_check = ad_map[i].ssam_check;
   1228 			}
   1229 			/* install flags */
   1230 			(*adp)->ad_type->sat_flags |= ad_map[i].ssam_flags;
   1231 
   1232 			/* install custom syntax routines */
   1233 			if( ad_map[i].ssam_syn_validate ||
   1234 				ad_map[i].ssam_syn_pretty )
   1235 			{
   1236 				Syntax *syn;
   1237 
   1238 				syntax = (*adp)->ad_type->sat_syntax;
   1239 
   1240 				syn = ch_malloc( sizeof( Syntax ) );
   1241 				*syn = *syntax;
   1242 
   1243 				if( ad_map[i].ssam_syn_validate ) {
   1244 					syn->ssyn_validate = ad_map[i].ssam_syn_validate;
   1245 				}
   1246 				if( ad_map[i].ssam_syn_pretty ) {
   1247 					syn->ssyn_pretty = ad_map[i].ssam_syn_pretty;
   1248 				}
   1249 
   1250 				(*adp)->ad_type->sat_syntax = syn;
   1251 			}
   1252 
   1253 			/* install custom rule routines */
   1254 			if( syntax != NULL ||
   1255 				ad_map[i].ssam_mr_convert ||
   1256 				ad_map[i].ssam_mr_normalize ||
   1257 				ad_map[i].ssam_mr_match ||
   1258 				ad_map[i].ssam_mr_indexer ||
   1259 				ad_map[i].ssam_mr_filter )
   1260 			{
   1261 				MatchingRule *mr = ch_malloc( sizeof( MatchingRule ) );
   1262 				*mr = *(*adp)->ad_type->sat_equality;
   1263 
   1264 				if ( syntax != NULL ) {
   1265 					mr->smr_syntax = (*adp)->ad_type->sat_syntax;
   1266 				}
   1267 				if ( ad_map[i].ssam_mr_convert ) {
   1268 					mr->smr_convert = ad_map[i].ssam_mr_convert;
   1269 				}
   1270 				if ( ad_map[i].ssam_mr_normalize ) {
   1271 					mr->smr_normalize = ad_map[i].ssam_mr_normalize;
   1272 				}
   1273 				if ( ad_map[i].ssam_mr_match ) {
   1274 					mr->smr_match = ad_map[i].ssam_mr_match;
   1275 				}
   1276 				if ( ad_map[i].ssam_mr_indexer ) {
   1277 					mr->smr_indexer = ad_map[i].ssam_mr_indexer;
   1278 				}
   1279 				if ( ad_map[i].ssam_mr_filter ) {
   1280 					mr->smr_filter = ad_map[i].ssam_mr_filter;
   1281 				}
   1282 
   1283 				(*adp)->ad_type->sat_equality = mr;
   1284 			}
   1285 		}
   1286 	}
   1287 
   1288 	for( i=0; oc_map[i].ssom_name; i++ ) {
   1289 		assert( oc_map[i].ssom_defn != NULL );
   1290 		{
   1291 			LDAPObjectClass *oc;
   1292 			int		code;
   1293 			const char	*err;
   1294 
   1295 			oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
   1296 				LDAP_SCHEMA_ALLOW_ALL );
   1297 			if ( !oc ) {
   1298 				fprintf( stderr, "slap_schema_load: ObjectClass "
   1299 					"\"%s\": %s before %s\n",
   1300 				 	oc_map[i].ssom_name, ldap_scherr2str(code), err );
   1301 				return code;
   1302 			}
   1303 
   1304 			if ( oc->oc_oid == NULL ) {
   1305 				fprintf( stderr, "slap_schema_load: ObjectClass "
   1306 					"\"%s\": no OID\n",
   1307 					oc_map[i].ssom_name );
   1308 				ldap_objectclass_free( oc );
   1309 				return LDAP_OTHER;
   1310 			}
   1311 
   1312 			code = oc_add(oc,0,NULL,NULL,&err);
   1313 			if ( code ) {
   1314 				ldap_objectclass_free( oc );
   1315 				fprintf( stderr, "slap_schema_load: ObjectClass "
   1316 					"\"%s\": %s: \"%s\"\n",
   1317 				 	oc_map[i].ssom_name, scherr2str(code), err);
   1318 				return code;
   1319 			}
   1320 			ldap_memfree(oc);
   1321 
   1322 		}
   1323 		{
   1324 			ObjectClass ** ocp = (ObjectClass **)
   1325 				&(((char *) &slap_schema)[oc_map[i].ssom_offset]);
   1326 
   1327 			assert( *ocp == NULL );
   1328 
   1329 			*ocp = oc_find( oc_map[i].ssom_name );
   1330 			if( *ocp == NULL ) {
   1331 				fprintf( stderr, "slap_schema_load: "
   1332 					"ObjectClass \"%s\": not defined in schema\n",
   1333 					oc_map[i].ssom_name );
   1334 				return LDAP_OBJECT_CLASS_VIOLATION;
   1335 			}
   1336 
   1337 			if( oc_map[i].ssom_check ) {
   1338 				/* install check routine */
   1339 				(*ocp)->soc_check = oc_map[i].ssom_check;
   1340 			}
   1341 			/* install flags */
   1342 			(*ocp)->soc_flags |= oc_map[i].ssom_flags;
   1343 		}
   1344 	}
   1345 
   1346 	return LDAP_SUCCESS;
   1347 }
   1348 
   1349 int
   1350 slap_schema_check( void )
   1351 {
   1352 	/* we should only be called once after schema_init() was called */
   1353 	assert( schema_init_done == 1 );
   1354 
   1355 	/*
   1356 	 * cycle thru attributeTypes to build matchingRuleUse
   1357 	 */
   1358 	if ( matching_rule_use_init() ) {
   1359 		return LDAP_OTHER;
   1360 	}
   1361 
   1362 	++schema_init_done;
   1363 	return LDAP_SUCCESS;
   1364 }
   1365 
   1366 static int rootDseObjectClass (
   1367 	Backend *be,
   1368 	Entry *e,
   1369 	ObjectClass *oc,
   1370 	const char** text,
   1371 	char *textbuf, size_t textlen )
   1372 {
   1373 	*text = textbuf;
   1374 
   1375 	if( e->e_nname.bv_len ) {
   1376 		snprintf( textbuf, textlen,
   1377 			"objectClass \"%s\" only allowed in the root DSE",
   1378 			oc->soc_oid );
   1379 		return LDAP_OBJECT_CLASS_VIOLATION;
   1380 	}
   1381 
   1382 	/* we should not be called for the root DSE */
   1383 	assert( 0 );
   1384 	return LDAP_SUCCESS;
   1385 }
   1386 
   1387 static int aliasObjectClass (
   1388 	Backend *be,
   1389 	Entry *e,
   1390 	ObjectClass *oc,
   1391 	const char** text,
   1392 	char *textbuf, size_t textlen )
   1393 {
   1394 	*text = textbuf;
   1395 
   1396 	if( !SLAP_ALIASES(be) ) {
   1397 		snprintf( textbuf, textlen,
   1398 			"objectClass \"%s\" not supported in context",
   1399 			oc->soc_oid );
   1400 		return LDAP_OBJECT_CLASS_VIOLATION;
   1401 	}
   1402 
   1403 	return LDAP_SUCCESS;
   1404 }
   1405 
   1406 static int referralObjectClass (
   1407 	Backend *be,
   1408 	Entry *e,
   1409 	ObjectClass *oc,
   1410 	const char** text,
   1411 	char *textbuf, size_t textlen )
   1412 {
   1413 	*text = textbuf;
   1414 
   1415 	if( !SLAP_REFERRALS(be) ) {
   1416 		snprintf( textbuf, textlen,
   1417 			"objectClass \"%s\" not supported in context",
   1418 			oc->soc_oid );
   1419 		return LDAP_OBJECT_CLASS_VIOLATION;
   1420 	}
   1421 
   1422 	return LDAP_SUCCESS;
   1423 }
   1424 
   1425 static int subentryObjectClass (
   1426 	Backend *be,
   1427 	Entry *e,
   1428 	ObjectClass *oc,
   1429 	const char** text,
   1430 	char *textbuf, size_t textlen )
   1431 {
   1432 	*text = textbuf;
   1433 
   1434 	if( !SLAP_SUBENTRIES(be) ) {
   1435 		snprintf( textbuf, textlen,
   1436 			"objectClass \"%s\" not supported in context",
   1437 			oc->soc_oid );
   1438 		return LDAP_OBJECT_CLASS_VIOLATION;
   1439 	}
   1440 
   1441 	if( oc != slap_schema.si_oc_subentry && !is_entry_subentry( e ) ) {
   1442 		snprintf( textbuf, textlen,
   1443 			"objectClass \"%s\" only allowed in subentries",
   1444 			oc->soc_oid );
   1445 		return LDAP_OBJECT_CLASS_VIOLATION;
   1446 	}
   1447 
   1448 	return LDAP_SUCCESS;
   1449 }
   1450 
   1451 #ifdef LDAP_DYNAMIC_OBJECTS
   1452 static int dynamicObjectClass (
   1453 	Backend *be,
   1454 	Entry *e,
   1455 	ObjectClass *oc,
   1456 	const char** text,
   1457 	char *textbuf, size_t textlen )
   1458 {
   1459 	*text = textbuf;
   1460 
   1461 	if( !SLAP_DYNAMIC(be) ) {
   1462 		snprintf( textbuf, textlen,
   1463 			"objectClass \"%s\" not supported in context",
   1464 			oc->soc_oid );
   1465 		return LDAP_OBJECT_CLASS_VIOLATION;
   1466 	}
   1467 
   1468 	return LDAP_SUCCESS;
   1469 }
   1470 #endif /* LDAP_DYNAMIC_OBJECTS */
   1471 
   1472 static int rootDseAttribute (
   1473 	Backend *be,
   1474 	Entry *e,
   1475 	Attribute *attr,
   1476 	const char** text,
   1477 	char *textbuf, size_t textlen )
   1478 {
   1479 	*text = textbuf;
   1480 
   1481 	if( e->e_nname.bv_len ) {
   1482 		snprintf( textbuf, textlen,
   1483 			"attribute \"%s\" only allowed in the root DSE",
   1484 			attr->a_desc->ad_cname.bv_val );
   1485 		return LDAP_OBJECT_CLASS_VIOLATION;
   1486 	}
   1487 
   1488 	/* we should not be called for the root DSE */
   1489 	assert( 0 );
   1490 	return LDAP_SUCCESS;
   1491 }
   1492 
   1493 static int aliasAttribute (
   1494 	Backend *be,
   1495 	Entry *e,
   1496 	Attribute *attr,
   1497 	const char** text,
   1498 	char *textbuf, size_t textlen )
   1499 {
   1500 	*text = textbuf;
   1501 
   1502 	if( !SLAP_ALIASES(be) ) {
   1503 		snprintf( textbuf, textlen,
   1504 			"attribute \"%s\" not supported in context",
   1505 			attr->a_desc->ad_cname.bv_val );
   1506 		return LDAP_OBJECT_CLASS_VIOLATION;
   1507 	}
   1508 
   1509 	if( !is_entry_alias( e ) ) {
   1510 		snprintf( textbuf, textlen,
   1511 			"attribute \"%s\" only allowed in the alias",
   1512 			attr->a_desc->ad_cname.bv_val );
   1513 		return LDAP_OBJECT_CLASS_VIOLATION;
   1514 	}
   1515 
   1516 	return LDAP_SUCCESS;
   1517 }
   1518 
   1519 static int referralAttribute (
   1520 	Backend *be,
   1521 	Entry *e,
   1522 	Attribute *attr,
   1523 	const char** text,
   1524 	char *textbuf, size_t textlen )
   1525 {
   1526 	*text = textbuf;
   1527 
   1528 	if( !SLAP_REFERRALS(be) ) {
   1529 		snprintf( textbuf, textlen,
   1530 			"attribute \"%s\" not supported in context",
   1531 			attr->a_desc->ad_cname.bv_val );
   1532 		return LDAP_OBJECT_CLASS_VIOLATION;
   1533 	}
   1534 
   1535 	if( !is_entry_referral( e ) ) {
   1536 		snprintf( textbuf, textlen,
   1537 			"attribute \"%s\" only allowed in the referral",
   1538 			attr->a_desc->ad_cname.bv_val );
   1539 		return LDAP_OBJECT_CLASS_VIOLATION;
   1540 	}
   1541 
   1542 	return LDAP_SUCCESS;
   1543 }
   1544 
   1545 static int subentryAttribute (
   1546 	Backend *be,
   1547 	Entry *e,
   1548 	Attribute *attr,
   1549 	const char** text,
   1550 	char *textbuf, size_t textlen )
   1551 {
   1552 	*text = textbuf;
   1553 
   1554 	if( !SLAP_SUBENTRIES(be) ) {
   1555 		snprintf( textbuf, textlen,
   1556 			"attribute \"%s\" not supported in context",
   1557 			attr->a_desc->ad_cname.bv_val );
   1558 		return LDAP_OBJECT_CLASS_VIOLATION;
   1559 	}
   1560 
   1561 	if( !is_entry_subentry( e ) ) {
   1562 		snprintf( textbuf, textlen,
   1563 			"attribute \"%s\" only allowed in the subentry",
   1564 			attr->a_desc->ad_cname.bv_val );
   1565 		return LDAP_OBJECT_CLASS_VIOLATION;
   1566 	}
   1567 
   1568 	return LDAP_SUCCESS;
   1569 }
   1570 
   1571 static int administrativeRoleAttribute (
   1572 	Backend *be,
   1573 	Entry *e,
   1574 	Attribute *attr,
   1575 	const char** text,
   1576 	char *textbuf, size_t textlen )
   1577 {
   1578 	*text = textbuf;
   1579 
   1580 	if( !SLAP_SUBENTRIES(be) ) {
   1581 		snprintf( textbuf, textlen,
   1582 			"attribute \"%s\" not supported in context",
   1583 			attr->a_desc->ad_cname.bv_val );
   1584 		return LDAP_OBJECT_CLASS_VIOLATION;
   1585 	}
   1586 
   1587 	snprintf( textbuf, textlen,
   1588 		"attribute \"%s\" not supported!",
   1589 		attr->a_desc->ad_cname.bv_val );
   1590 	return LDAP_OBJECT_CLASS_VIOLATION;
   1591 }
   1592 
   1593 #ifdef LDAP_DYNAMIC_OBJECTS
   1594 static int dynamicAttribute (
   1595 	Backend *be,
   1596 	Entry *e,
   1597 	Attribute *attr,
   1598 	const char** text,
   1599 	char *textbuf, size_t textlen )
   1600 {
   1601 	*text = textbuf;
   1602 
   1603 	if( !SLAP_DYNAMIC(be) ) {
   1604 		snprintf( textbuf, textlen,
   1605 			"attribute \"%s\" not supported in context",
   1606 			attr->a_desc->ad_cname.bv_val );
   1607 		return LDAP_OBJECT_CLASS_VIOLATION;
   1608 	}
   1609 
   1610 	if( !is_entry_dynamicObject( e ) ) {
   1611 		snprintf( textbuf, textlen,
   1612 			"attribute \"%s\" only allowed in dynamic object",
   1613 			attr->a_desc->ad_cname.bv_val );
   1614 		return LDAP_OBJECT_CLASS_VIOLATION;
   1615 	}
   1616 
   1617 	return LDAP_SUCCESS;
   1618 }
   1619 #endif /* LDAP_DYNAMIC_OBJECTS */
   1620