schema_prep.c 32.3 KB
Newer Older
1
2
3
/* schema_init.c - init builtin schema */
/* $OpenLDAP$ */
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5
6
7
8
9
10
11
12
13
14
15
16
17
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */

#include "portable.h"

#include <stdio.h>

#include <ac/ctype.h>
#include <ac/string.h>
#include <ac/socket.h>

#include "slap.h"
#include "ldap_pvt.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
18
#include "ldap_pvt_uc.h"
19
20
21
22
23
24
25

int schema_init_done = 0;

struct slap_internal_schema slap_schema;

static int
objectClassMatch(
26
	int *matchp,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
27
	slap_mask_t flags,
28
29
30
31
32
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
33
	struct berval *a = (struct berval *) assertedValue;
Howard Chu's avatar
Howard Chu committed
34
35
	ObjectClass *oc = oc_bvfind( value );
	ObjectClass *asserted = oc_bvfind( a );
36

37
38
39
40
41
42
43
44
45
46
47
#if 1
#ifdef NEW_LOGGING
	LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
		   "> objectClassMatch(%s, %s)\n",
		   value->bv_val, a->bv_val ));
#else
	Debug( LDAP_DEBUG_TRACE, "> objectClassMatch(%s,%s)\n",
		value->bv_val, a->bv_val, 0 );
#endif
#endif

48
	if( asserted == NULL ) {
49
		if( OID_LEADCHAR( *a->bv_val ) ) {
50
51
52
53
54
55
			/* OID form, return FALSE */
			*matchp = 1;
			return LDAP_SUCCESS;
		}

		/* desc form, return undefined */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
56
		return SLAPD_COMPARE_UNDEFINED;
57
58
59
	}

	if ( oc == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
60
61
		/* unrecognized stored value */
		return SLAPD_COMPARE_UNDEFINED;
62
63
	}

64
	if( SLAP_IS_MR_VALUE_SYNTAX_MATCH( flags ) ) {
65
66
67
68
69
		*matchp = ( asserted != oc );
	} else {
		*matchp = !is_object_subclass( asserted, oc );
	}

70
#if 1
71
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
72
	LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
73
		   "< objectClassMatch(%s, %s) = %d\n",
Gary Williams's avatar
Gary Williams committed
74
		   value->bv_val, a->bv_val, *matchp ));
75
#else
76
	Debug( LDAP_DEBUG_TRACE, "< objectClassMatch(%s,%s) = %d\n",
77
		value->bv_val, a->bv_val, *matchp );
78
#endif
79
80
#endif

81
82
83
	return LDAP_SUCCESS;
}

84
85
86
#if 1
#define structuralObjectClassMatch objectClassMatch
#else
87
88
89
static int
structuralObjectClassMatch(
	int *matchp,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
90
	slap_mask_t flags,
91
92
93
94
95
96
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	struct berval *a = (struct berval *) assertedValue;
Howard Chu's avatar
Howard Chu committed
97
98
	ObjectClass *oc = oc_bvfind( value );
	ObjectClass *asserted = oc_bvfind( a );
99

100
101
102
103
104
105
106
107
108
109
110
#if 1
#ifdef NEW_LOGGING
	LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
		   "> structuralObjectClassMatch(%s, %s)\n",
		   value->bv_val, a->bv_val ));
#else
	Debug( LDAP_DEBUG_TRACE, "> structuralObjectClassMatch(%s,%s)\n",
		value->bv_val, a->bv_val, 0 );
#endif
#endif

111
112
113
114
115
116
117
118
119
120
	if( asserted == NULL ) {
		if( OID_LEADCHAR( *a->bv_val ) ) {
			/* OID form, return FALSE */
			*matchp = 1;
			return LDAP_SUCCESS;
		}

		/* desc form, return undefined */
		return SLAPD_COMPARE_UNDEFINED;
	}
121

122
123
124
125
126
127
128
	if ( oc == NULL ) {
		/* unrecognized stored value */
		return SLAPD_COMPARE_UNDEFINED;
	}

	*matchp = ( asserted != oc );

129
#if 1
130
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
131
	LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
132
		   "< structuralObjectClassMatch( %s, %s ) = %d\n",
Gary Williams's avatar
Gary Williams committed
133
		   value->bv_val, a->bv_val, *matchp ));
134
#else
135
	Debug( LDAP_DEBUG_TRACE, "< structuralObjectClassMatch(%s,%s) = %d\n",
136
		value->bv_val, a->bv_val, *matchp );
137
#endif
138
#endif
139
140
141

	return LDAP_SUCCESS;
}
142
#endif
143

Kurt Zeilenga's avatar
Kurt Zeilenga committed
144
static ObjectClassSchemaCheckFN rootDseObjectClass;
145
146
static ObjectClassSchemaCheckFN aliasObjectClass;
static ObjectClassSchemaCheckFN referralObjectClass;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
147
static ObjectClassSchemaCheckFN subentryObjectClass;
148
static ObjectClassSchemaCheckFN dynamicObjectClass;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
149

Kurt Zeilenga's avatar
Kurt Zeilenga committed
150
static struct slap_schema_oc_map {
151
	char *ssom_name;
152
153
	char *ssom_defn;
	ObjectClassSchemaCheckFN *ssom_check;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
154
	slap_mask_t ssom_flags;
155
156
	size_t ssom_offset;
} oc_map[] = {
157
158
159
	{ "top", "( 2.5.6.0 NAME 'top' "
			"DESC 'top of the superclass chain' "
			"ABSTRACT MUST objectClass )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
160
		0, 0, offsetof(struct slap_internal_schema, si_oc_top) },
161
162
163
164
	{ "extensibleObject", "( 1.3.6.1.4.1.1466.101.120.111 "
			"NAME 'extensibleObject' "
			"DESC 'RFC2252: extensible object' "
			"SUP top AUXILIARY )",
165
166
		0, SLAP_OC_OPERATIONAL,
		offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
167
168
169
170
	{ "alias", "( 2.5.6.1 NAME 'alias' "
			"DESC 'RFC2256: an alias' "
			"SUP top STRUCTURAL "
			"MUST aliasedObjectName )",
171
		aliasObjectClass, SLAP_OC_ALIAS|SLAP_OC_OPERATIONAL,
172
		offsetof(struct slap_internal_schema, si_oc_alias) },
173
174
175
	{ "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
			"DESC 'namedref: named subordinate referral' "
			"SUP top STRUCTURAL MUST ref )",
176
		referralObjectClass, SLAP_OC_REFERRAL|SLAP_OC_OPERATIONAL,
177
		offsetof(struct slap_internal_schema, si_oc_referral) },
178
179
180
	{ "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
			"NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
			"DESC 'OpenLDAP Root DSE object' "
181
			"SUP top STRUCTURAL MAY cn )",
182
		rootDseObjectClass, SLAP_OC_OPERATIONAL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
183
		offsetof(struct slap_internal_schema, si_oc_rootdse) },
184
185
186
	{ "subentry", "( 2.5.20.0 NAME 'subentry' "
			"SUP top STRUCTURAL "
			"MUST ( cn $ subtreeSpecification ) )",
187
		subentryObjectClass, SLAP_OC_SUBENTRY|SLAP_OC_OPERATIONAL,
188
		offsetof(struct slap_internal_schema, si_oc_subentry) },
189
190
	{ "subschema", "( 2.5.20.1 NAME 'subschema' "
		"DESC 'RFC2252: controlling subschema (sub)entry' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
191
		"AUXILIARY "
192
193
		"MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
			"objectClasses $ attributeTypes $ matchingRules $ "
194
			"matchingRuleUse ) )",
195
		subentryObjectClass, SLAP_OC_OPERATIONAL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
196
		offsetof(struct slap_internal_schema, si_oc_subschema) },
197
198
199
200
	{ "monitor", "( 1.3.6.1.4.1.4203.666.3.2 NAME 'monitor' "
		"DESC 'OpenLDAP system monitoring' "
		"STRUCTURAL "
		"MUST cn )",
201
202
		0, SLAP_OC_OPERATIONAL,
		offsetof(struct slap_internal_schema, si_oc_monitor) },
203
204
	{ "collectiveAttributeSubentry", "( 2.5.20.2 "
			"NAME 'collectiveAttributeSubentry' "
205
			"AUXILIARY )",
206
207
		subentryObjectClass,
		SLAP_OC_COLLECTIVEATTRIBUTESUBENTRY|SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
208
		offsetof(struct slap_internal_schema, si_oc_collectiveAttributeSubentry) },
209
210
211
212
	{ "dynamicObject", "( 1.3.6.1.4.1.1466.101.119.2 "
			"NAME 'dynamicObject' "
			"DESC 'RFC2589: Dynamic Object' "
			"SUP top AUXILIARY )",
213
		dynamicObjectClass, SLAP_OC_DYNAMICOBJECT,
214
		offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
215
	{ NULL, NULL, NULL, 0, 0 }
216
217
};

218
static AttributeTypeSchemaCheckFN rootDseAttribute;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
219
static AttributeTypeSchemaCheckFN aliasAttribute;
220
static AttributeTypeSchemaCheckFN referralAttribute;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
221
static AttributeTypeSchemaCheckFN subentryAttribute;
222
static AttributeTypeSchemaCheckFN administrativeRoleAttribute;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
223
static AttributeTypeSchemaCheckFN dynamicAttribute;
224

Kurt Zeilenga's avatar
Kurt Zeilenga committed
225
static struct slap_schema_ad_map {
226
	char *ssam_name;
227
228
	char *ssam_defn;
	AttributeTypeSchemaCheckFN *ssam_check;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
229
	slap_mask_t ssam_flags;
230
	slap_mr_match_func *ssam_match;
231
232
	slap_mr_indexer_func *ssam_indexer;
	slap_mr_filter_func *ssam_filter;
233
234
	size_t ssam_offset;
} ad_map[] = {
235
236
237
238
	{ "objectClass", "( 2.5.4.0 NAME 'objectClass' "
			"DESC 'RFC2256: object classes of the entity' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
239
		NULL, SLAP_AT_FINAL, objectClassMatch, NULL, NULL,
240
		offsetof(struct slap_internal_schema, si_ad_objectClass) },
241
242

	/* user entry operational attributes */
243
244
245
246
	{ "structuralObjectClass", "( 2.5.21.9 NAME 'structuralObjectClass' "
			"DESC 'X.500(93): structural object class of entry' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
247
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
248
		NULL, 0, structuralObjectClassMatch, NULL, NULL,
249
		offsetof(struct slap_internal_schema, si_ad_structuralObjectClass) },
250
251
252
253
254
255
	{ "createTimestamp", "( 2.5.18.1 NAME 'createTimestamp' "
			"DESC 'RFC2252: time which object was created' "
			"EQUALITY generalizedTimeMatch "
			"ORDERING generalizedTimeOrderingMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
256
		NULL, 0, NULL, NULL, NULL,
257
		offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
258
259
260
261
262
263
	{ "modifyTimestamp", "( 2.5.18.2 NAME 'modifyTimestamp' "
			"DESC 'RFC2252: time which object was last modified' "
			"EQUALITY generalizedTimeMatch "
			"ORDERING generalizedTimeOrderingMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
264
		NULL, 0, NULL, NULL, NULL,
265
		offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
266
267
268
269
270
	{ "creatorsName", "( 2.5.18.3 NAME 'creatorsName' "
			"DESC 'RFC2252: name of creator' "
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
271
		NULL, 0, NULL, NULL, NULL,
272
273
274
275
276
277
		offsetof(struct slap_internal_schema, si_ad_creatorsName) },
	{ "modifiersName", "( 2.5.18.4 NAME 'modifiersName' "
			"DESC 'RFC2252: name of last modifier' "
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
278
		NULL, 0, NULL, NULL, NULL,
279
280
281
282
283
284
		offsetof(struct slap_internal_schema, si_ad_modifiersName) },
	{ "hasSubordinates", "( 2.5.18.9 NAME 'hasSubordinates' "
			"DESC 'X.501: entry has children' "
			"EQUALITY booleanMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
285
		NULL, 0, NULL, NULL, NULL,
286
		offsetof(struct slap_internal_schema, si_ad_hasSubordinates) },
287
288
289
	{ "subschemaSubentry", "( 2.5.18.10 NAME 'subschemaSubentry' "
			"DESC 'RFC2252: name of controlling subschema entry' "
			"EQUALITY distinguishedNameMatch "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
290
291
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE "
			"NO-USER-MODIFICATION USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
292
		NULL, 0, NULL, NULL, NULL,
293
		offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
294
295
	{ "collectiveAttributeSubentries", "( 2.5.18.12 "
			"NAME 'collectiveAttributeSubentries' "
296
297
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
298
			"NO-USER-MODIFICATION USAGE directoryOperation )",
299
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
300
		offsetof(struct slap_internal_schema, si_ad_collectiveSubentries) },
301
302
303
304
	{ "collectiveExclusions", "( 2.5.18.7 NAME 'collectiveExclusions' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
			"USAGE directoryOperation )",
305
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
306
		offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
307

308
309
310
311
312
	{ "entryUUID", "( 1.3.6.1.4.1.4203.666.1.6 NAME 'entryUUID' "   
			"DESC 'LCUP/LDUP: universally unique identifier' "
			"EQUALITY octetStringMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
313
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
314
315
316
317
318
319
		offsetof(struct slap_internal_schema, si_ad_entryUUID) },
	{ "entryCSN", "( 1.3.6.1.4.1.4203.666.1.7 NAME 'entryCSN' "
			"DESC 'LCUP/LDUP: change sequence number' "
			"EQUALITY octetStringMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
320
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
321
322
		offsetof(struct slap_internal_schema, si_ad_entryCSN) },

323
	/* root DSE attributes */
324
325
326
	{ "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' "
			"DESC 'RFC2252: alternative servers' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
327
		rootDseAttribute, 0, NULL, NULL, NULL,
328
		offsetof(struct slap_internal_schema, si_ad_altServer) },
329
330
331
332
	{ "namingContexts", "( 1.3.6.1.4.1.1466.101.120.5 "
			"NAME 'namingContexts' "
			"DESC 'RFC2252: naming contexts' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
333
		rootDseAttribute, 0, NULL, NULL, NULL,
334
		offsetof(struct slap_internal_schema, si_ad_namingContexts) },
335
336
	{ "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
			"NAME 'supportedControl' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
337
338
			"DESC 'RFC2252: supported controls' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
339
		rootDseAttribute, 0, NULL, NULL, NULL,
340
		offsetof(struct slap_internal_schema, si_ad_supportedControl) },
341
342
343
344
	{ "supportedExtension", "( 1.3.6.1.4.1.1466.101.120.7 "
			"NAME 'supportedExtension' "
			"DESC 'RFC2252: supported extended operations' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
345
		rootDseAttribute, 0, NULL, NULL, NULL,
346
		offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
347
348
349
350
	{ "supportedLDAPVersion", "( 1.3.6.1.4.1.1466.101.120.15 "
			"NAME 'supportedLDAPVersion' "
			"DESC 'RFC2252: supported LDAP versions' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
351
		rootDseAttribute, 0, NULL, NULL, NULL,
352
		offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
353
354
355
356
	{ "supportedSASLMechanisms", "( 1.3.6.1.4.1.1466.101.120.14 "
			"NAME 'supportedSASLMechanisms' "
			"DESC 'RFC2252: supported SASL mechanisms'"
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
357
		rootDseAttribute, 0, NULL, NULL, NULL,
358
		offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
359
360
361
362
363
364
	{ "supportedFeatures", "( 1.3.6.1.4.1.4203.1.3.5 "
			"NAME 'supportedFeatures' "
			"DESC 'features supported by the server' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
			"USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
365
		rootDseAttribute, 0, NULL, NULL, NULL,
366
		offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
367
368
369
370
371
372
373
374
375
	{ "monitorContext", "( 1.3.6.1.4.1.4203.666.1.10 "
			"NAME 'monitorContext' "
			"DESC 'monitor context' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
			"SINGLE-VALUE NO-USER-MODIFICATION "
			"USAGE dSAOperation )",
		rootDseAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
		offsetof(struct slap_internal_schema, si_ad_monitorContext) },
376
377
378
379
380
381
	{ "vendorName", "( 1.3.6.1.1.4 NAME 'vendorName' "
			"DESC 'RFC3045: name of implementation vendor' "
			"EQUALITY 1.3.6.1.4.1.1466.109.114.1 "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
			"SINGLE-VALUE NO-USER-MODIFICATION "
			"USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
382
		rootDseAttribute, 0, NULL, NULL, NULL,
383
384
385
386
387
388
389
		offsetof(struct slap_internal_schema, si_ad_vendorName) },
	{ "vendorVersion", "( 1.3.6.1.1.5 NAME 'vendorVersion' "
			"DESC 'RFC3045: version of implementation' "
			"EQUALITY 1.3.6.1.4.1.1466.109.114.1 "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
			"SINGLE-VALUE NO-USER-MODIFICATION "
			"USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
390
		rootDseAttribute, 0, NULL, NULL, NULL,
391
392
393
394
395
396
397
		offsetof(struct slap_internal_schema, si_ad_vendorVersion) },

	/* subentry attributes */
	{ "administrativeRole", "( 2.5.18.5 NAME 'administrativeRole' "
			"EQUALITY objectIdentifierMatch "
			"USAGE directoryOperation "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
398
		administrativeRoleAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
399
400
401
402
403
		offsetof(struct slap_internal_schema, si_ad_administrativeRole) },
	{ "subtreeSpecification", "( 2.5.18.6 NAME 'subtreeSpecification' "
			"SINGLE-VALUE "
			"USAGE directoryOperation "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.45 )",
404
		subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
405
		offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
406

407
	/* subschema subentry attributes */
408
409
410
411
412
	{ "ditStructureRules", "( 2.5.21.1 NAME 'dITStructureRules' "
			"DESC 'RFC2252: DIT structure rules' "
			"EQUALITY integerFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 "
			"USAGE directoryOperation ) ",
413
		subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
414
415
416
417
418
		offsetof(struct slap_internal_schema, si_ad_ditStructureRules) },
	{ "ditContentRules", "( 2.5.21.2 NAME 'dITContentRules' "
			"DESC 'RFC2252: DIT content rules' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )",
419
		subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
420
		offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
421
422
423
424
	{ "matchingRules", "( 2.5.21.4 NAME 'matchingRules' "
			"DESC 'RFC2252: matching rules' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
425
		subentryAttribute, 0, NULL, NULL, NULL,
426
		offsetof(struct slap_internal_schema, si_ad_matchingRules) },
427
428
429
430
	{ "attributeTypes", "( 2.5.21.5 NAME 'attributeTypes' "
			"DESC 'RFC2252: attribute types' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
431
		subentryAttribute, 0, NULL, NULL, NULL,
432
433
434
435
436
		offsetof(struct slap_internal_schema, si_ad_attributeTypes) },
	{ "objectClasses", "( 2.5.21.6 NAME 'objectClasses' "
			"DESC 'RFC2252: object classes' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
437
		subentryAttribute, 0, NULL, NULL, NULL,
438
		offsetof(struct slap_internal_schema, si_ad_objectClasses) },
439
440
441
442
	{ "nameForms", "( 2.5.21.7 NAME 'nameForms' "
			"DESC 'RFC2252: name forms ' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )",
443
		subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
444
		offsetof(struct slap_internal_schema, si_ad_nameForms) },
445
	{ "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
446
447
448
			"DESC 'RFC2252: matching rule uses' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
449
		subentryAttribute, SLAP_AT_HIDE, NULL, NULL, NULL,
450
		offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
451

452
453
454
455
	{ "ldapSyntaxes", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' "
			"DESC 'RFC2252: LDAP syntaxes' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
456
		subentryAttribute, 0, NULL, NULL, NULL,
457
458
		offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },

459
	/* knowledge information */
460
461
462
463
464
	{ "aliasedObjectName", "( 2.5.4.1 "
			"NAME ( 'aliasedObjectName' 'aliasedEntryName' ) "
			"DESC 'RFC2256: name of aliased object' "
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
465
		aliasAttribute, SLAP_AT_FINAL, NULL, NULL, NULL,
466
		offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
467
468
469
470
471
	{ "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
			"DESC 'namedref: subordinate referral URL' "
			"EQUALITY caseExactMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
			"USAGE distributedOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
472
		referralAttribute, 0, NULL, NULL, NULL,
473
474
		offsetof(struct slap_internal_schema, si_ad_ref) },

Kurt Zeilenga's avatar
Kurt Zeilenga committed
475
	/* access control internals */
476
477
478
479
480
	{ "entry", "( 1.3.6.1.4.1.4203.1.3.1 "
			"NAME 'entry' "
			"DESC 'OpenLDAP ACL entry pseudo-attribute' "
			"SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
481
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
482
		offsetof(struct slap_internal_schema, si_ad_entry) },
483
484
485
486
487
	{ "children", "( 1.3.6.1.4.1.4203.1.3.2 "
			"NAME 'children' "
			"DESC 'OpenLDAP ACL children pseudo-attribute' "
			"SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
488
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
489
		offsetof(struct slap_internal_schema, si_ad_children) },
490
	{ "saslAuthzTo", "( 1.3.6.1.4.1.4203.666.1.8 "
491
492
493
494
			"NAME 'saslAuthzTo' "
			"DESC 'SASL proxy authorization targets' "
			"EQUALITY caseExactMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
495
496
			"USAGE distributedOperation )",
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
497
		offsetof(struct slap_internal_schema, si_ad_saslAuthzTo) },
498
	{ "saslAuthzFrom", "( 1.3.6.1.4.1.4203.666.1.9 "
499
500
501
502
			"NAME 'saslAuthzFrom' "
			"DESC 'SASL proxy authorization sources' "
			"EQUALITY caseExactMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
503
504
			"USAGE distributedOperation )",
		NULL, SLAP_AT_HIDE, NULL, NULL, NULL,
505
		offsetof(struct slap_internal_schema, si_ad_saslAuthzFrom) },
506
#ifdef SLAPD_ACI_ENABLED
507
508
509
510
511
512
	{ "OpenLDAPaci", "( 1.3.6.1.4.1.4203.666.1.5 "
			"NAME 'OpenLDAPaci' "
			"DESC 'OpenLDAP access control information (experimental)' "
			"EQUALITY OpenLDAPaciMatch "
			"SYNTAX 1.3.6.1.4.1.4203.666.2.1 "
			"USAGE directoryOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
513
		NULL, 0, NULL, NULL, NULL,
514
515
		offsetof(struct slap_internal_schema, si_ad_aci) },
#endif
516

517
518
519
520
	{ "entryTtl", "( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl' "
			"DESC 'RFC2589: entry time-to-live' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE "
			"NO-USER-MODIFICATION USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
521
		dynamicAttribute, 0, NULL, NULL, NULL,
522
523
524
525
526
527
		offsetof(struct slap_internal_schema, si_ad_entryTtl) },
	{ "dynamicSubtrees", "( 1.3.6.1.4.1.1466.101.119.4 "
			"NAME 'dynamicSubtrees' "
			"DESC 'RFC2589: dynamic subtrees' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
			"USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
528
		rootDseAttribute, 0, NULL, NULL, NULL,
529
530
		offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },

531
	/* userApplication attributes (which system schema depends upon) */
532
533
534
535
	{ "distinguishedName", "( 2.5.4.49 NAME 'distinguishedName' "
			"DESC 'RFC2256: common supertype of DN attributes' "
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
536
		NULL, SLAP_AT_ABSTRACT, NULL, NULL, NULL,
537
		offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
538
539
540
541
542
	{ "name", "( 2.5.4.41 NAME 'name' "
			"DESC 'RFC2256: common supertype of name attributes' "
			"EQUALITY caseIgnoreMatch "
			"SUBSTR caseIgnoreSubstringsMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )",
543
		NULL, SLAP_AT_ABSTRACT, NULL, NULL, NULL,
544
545
546
547
		offsetof(struct slap_internal_schema, si_ad_name) },
	{ "cn", "( 2.5.4.3 NAME ( 'cn' 'commonName' ) "
			"DESC 'RFC2256: common name(s) for which the entity is known by' "
			"SUP name )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
548
		NULL, 0, NULL, NULL, NULL,
549
550
551
552
553
		offsetof(struct slap_internal_schema, si_ad_cn) },
	{ "userPassword", "( 2.5.4.35 NAME 'userPassword' "
			"DESC 'RFC2256/2307: password of user' "
			"EQUALITY octetStringMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )",
554
		NULL, 0, NULL, NULL, NULL,
555
		offsetof(struct slap_internal_schema, si_ad_userPassword) },
556
557

#ifdef SLAPD_AUTHPASSWD
558
559
560
561
562
	{ "authPassword", "( 1.3.6.1.4.1.4203.1.3.4 "
			"NAME 'authPassword' "
			"DESC 'RFC3112: authentication password attribute' "
			"EQUALITY 1.3.6.1.4.1.4203.1.2.2 "
			"SYNTAX 1.3.6.1.4.1.4203.1.1.2 )",
563
		NULL, 0,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
564
		NULL, NULL, NULL,
565
566
567
568
569
570
571
		offsetof(struct slap_internal_schema, si_ad_authPassword) },
	{ "supportedAuthPasswordSchemes", "( 1.3.6.1.4.1.4203.1.3.3 "
			"NAME 'supportedAuthPasswordSchemes' "
			"DESC 'RFC3112: supported authPassword schemes' "
			"EQUALITY caseExactIA5Match "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} "
			"USAGE dSAOperation )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
572
		subschemaAttribute, 0, NULL, NULL, NULL,
573
		offsetof(struct slap_internal_schema, si_ad_authPassword) },
574
#endif
575
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
576
577
578
579
580
581
	{ "krbName", "( 1.3.6.1.4.1.250.1.32 "
			"NAME ( 'krbName' 'kerberosName' ) "
			"DESC 'Kerberos principal associated with object' "
			"EQUALITY caseIgnoreIA5Match "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 "
			"SINGLE-VALUE )",
582
		NULL, 0, NULL, NULL, NULL,
583
584
585
		offsetof(struct slap_internal_schema, si_ad_krbName) },
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
586
	{ NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
587
588
};

589
590
591
static AttributeType slap_at_undefined = {
	{ "1.1.1", NULL, NULL, 1, NULL,
		NULL, NULL, NULL, NULL,
592
		0, 0, 0, 1, 3 }, /* LDAPAttributeType */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
593
	{ sizeof("UNDEFINED")-1, "UNDEFINED" }, /* cname */
594
595
596
597
	NULL, /* sup */
	NULL, /* subtypes */
	NULL, NULL, NULL, NULL,	/* matching rules */
	NULL, /* syntax (this may need to be defined) */
598
599
	(AttributeTypeSchemaCheckFN *) 0, /* schema check function */
	SLAP_AT_ABSTRACT|SLAP_AT_FINAL,	/* mask */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
600
601
	NULL, /* next */
	NULL /* attribute description */
602
	/* mutex (don't know how to initialize it :) */
603
};
604

Kurt Zeilenga's avatar
Kurt Zeilenga committed
605
static struct slap_schema_mr_map {
606
607
608
609
610
611
612
613
614
615
	char *ssmm_name;
	size_t ssmm_offset;
} mr_map[] = {
	{ "distinguishedNameMatch",
		offsetof(struct slap_internal_schema, si_mr_distinguishedNameMatch) },
	{ "integerMatch",
		offsetof(struct slap_internal_schema, si_mr_integerMatch) },
	{ NULL, 0 }
};

Kurt Zeilenga's avatar
Kurt Zeilenga committed
616
static struct slap_schema_syn_map {
617
618
619
	char *sssm_name;
	size_t sssm_offset;
} syn_map[] = {
620
621
	{ "1.3.6.1.4.1.1466.115.121.1.40",
		offsetof(struct slap_internal_schema, si_syn_octetString) },
622
623
624
625
626
627
628
	{ "1.3.6.1.4.1.1466.115.121.1.12",
		offsetof(struct slap_internal_schema, si_syn_distinguishedName) },
	{ "1.3.6.1.4.1.1466.115.121.1.27",
		offsetof(struct slap_internal_schema, si_syn_integer) },
	{ NULL, 0 }
};

629
int
630
631
slap_schema_load( void )
{
632
	int i;
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665

	for( i=0; syn_map[i].sssm_name; i++ ) {
		Syntax ** synp = (Syntax **)
			&(((char *) &slap_schema)[syn_map[i].sssm_offset]);

		assert( *synp == NULL );

		*synp = syn_find( syn_map[i].sssm_name );

		if( *synp == NULL ) {
			fprintf( stderr, "slap_schema_check: "
				"No syntax \"%s\" defined in schema\n",
				syn_map[i].sssm_name );
			return LDAP_INVALID_SYNTAX;
		}
	}

	for( i=0; mr_map[i].ssmm_name; i++ ) {
		MatchingRule ** mrp = (MatchingRule **)
			&(((char *) &slap_schema)[mr_map[i].ssmm_offset]);

		assert( *mrp == NULL );

		*mrp = mr_find( mr_map[i].ssmm_name );

		if( *mrp == NULL ) {
			fprintf( stderr, "slap_schema_check: "
				"No matching rule \"%s\" defined in schema\n",
				mr_map[i].ssmm_name );
			return LDAP_INAPPROPRIATE_MATCHING;
		}
	}

666
	for( i=0; ad_map[i].ssam_name; i++ ) {
667
668
		assert( ad_map[i].ssam_defn != NULL );
		{
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
			LDAPAttributeType *at;
			int		code;
			const char	*err;

			at = ldap_str2attributetype( ad_map[i].ssam_defn,
				&code, &err, LDAP_SCHEMA_ALLOW_ALL );
			if ( !at ) {
				fprintf( stderr,
					"slap_schema_load: %s: %s before %s\n",
					 ad_map[i].ssam_name, ldap_scherr2str(code), err );
				return code;
			}

			if ( at->at_oid == NULL ) {
				fprintf( stderr, "slap_schema_load: "
					"attributeType \"%s\" has no OID\n",
					ad_map[i].ssam_name );
				return LDAP_OTHER;
			}

			code = at_add( at, &err );
			if ( code ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: %s: \"%s\"\n",
					 ad_map[i].ssam_name, scherr2str(code), err );
				return code;
			}
			ldap_memfree( at );
		}
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
		{
			int rc;
			const char *text;

			AttributeDescription ** adp = (AttributeDescription **)
				&(((char *) &slap_schema)[ad_map[i].ssam_offset]);

			assert( *adp == NULL );

			rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );
			if( rc != LDAP_SUCCESS ) {
				fprintf( stderr, "slap_schema_check: "
					"No attribute \"%s\" defined in schema\n",
					ad_map[i].ssam_name );
				return rc;
			}

			if( ad_map[i].ssam_check ) {
				/* install check routine */
				(*adp)->ad_type->sat_check = ad_map[i].ssam_check;
			}
			/* install flags */
			(*adp)->ad_type->sat_flags |= ad_map[i].ssam_flags;

			if( ad_map[i].ssam_match ) {
				/* install custom matching routine */
				(*adp)->ad_type->sat_equality->smr_match = ad_map[i].ssam_match;
			}
		}
727
	}
728
729

	for( i=0; oc_map[i].ssom_name; i++ ) {
730
731
		assert( oc_map[i].ssom_defn != NULL );
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
732
733
734
			LDAPObjectClass *oc;
			int		code;
			const char	*err;
735

Kurt Zeilenga's avatar
Kurt Zeilenga committed
736
737
738
739
740
741
742
743
			oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
				LDAP_SCHEMA_ALLOW_ALL );
			if ( !oc ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: %s before %s\n",
				 	oc_map[i].ssom_name, ldap_scherr2str(code), err );
				return code;
			}
744

Kurt Zeilenga's avatar
Kurt Zeilenga committed
745
746
747
748
749
750
			if ( oc->oc_oid == NULL ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: objectclass has no OID\n",
					oc_map[i].ssom_name );
				return LDAP_OTHER;
			}
751

752
			code = oc_add(oc,0,&err);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
753
754
755
756
757
758
759
760
761
			if ( code ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: %s: \"%s\"\n",
				 	oc_map[i].ssom_name, scherr2str(code), err);
				return code;
			}

			ldap_memfree(oc);
		}
762
763
764
		{
			ObjectClass ** ocp = (ObjectClass **)
				&(((char *) &slap_schema)[oc_map[i].ssom_offset]);
765

766
			assert( *ocp == NULL );
767

768
769
770
771
772
773
774
			*ocp = oc_find( oc_map[i].ssom_name );
			if( *ocp == NULL ) {
				fprintf( stderr, "slap_schema_check: "
					"No objectClass \"%s\" defined in schema\n",
					oc_map[i].ssom_name );
				return LDAP_OBJECT_CLASS_VIOLATION;
			}
775

776
777
778
779
780
781
			if( oc_map[i].ssom_check ) {
				/* install check routine */
				(*ocp)->soc_check = oc_map[i].ssom_check;
			}
			/* install flags */
			(*ocp)->soc_flags |= oc_map[i].ssom_flags;
782
783
784
		}
	}

785
	slap_at_undefined.sat_syntax = slap_schema.si_syn_distinguishedName;
786
787
	slap_schema.si_at_undefined = &slap_at_undefined;

788
789
	return LDAP_SUCCESS;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
790

791
792
793
794
795
int
slap_schema_check( void )
{
	/* we should only be called once after schema_init() was called */
	assert( schema_init_done == 1 );
796

797
798
799
	++schema_init_done;
	return LDAP_SUCCESS;
}
800

Kurt Zeilenga's avatar
Kurt Zeilenga committed
801
static int rootDseObjectClass (
802
	Backend *be,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
803
804
805
806
807
808
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
809

Kurt Zeilenga's avatar
Kurt Zeilenga committed
810
811
812
813
814
815
816
817
818
819
820
821
	if( e->e_nname.bv_len ) {
		snprintf( textbuf, textlen,
			"objectClass \"%s\" only allowed in the root DSE",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	/* we should not be called for the root DSE */
	assert( 0 );
	return LDAP_SUCCESS;
}

822
823
824
825
826
827
828
static int aliasObjectClass (
	Backend *be,
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
829
830
	*text = textbuf;

831
832
833
834
835
836
	if( !SLAP_ALIASES(be) ) {
		snprintf( textbuf, textlen,
			"objectClass \"%s\" not supported in context",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
837

838
839
840
841
842
843
844
845
846
847
	return LDAP_SUCCESS;
}

static int referralObjectClass (
	Backend *be,
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
848
849
	*text = textbuf;

850
851
852
853
854
855
	if( !SLAP_REFERRALS(be) ) {
		snprintf( textbuf, textlen,
			"objectClass \"%s\" not supported in context",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
856

857
858
859
	return LDAP_SUCCESS;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
860
static int subentryObjectClass (
861
	Backend *be,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
862
863
864
865
866
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
867
868
	*text = textbuf;

869
870
871
872
873
874
875
876
	if( !SLAP_SUBENTRIES(be) ) {
		snprintf( textbuf, textlen,
			"objectClass \"%s\" not supported in context",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	if( oc != slap_schema.si_oc_subentry && !is_entry_subentry( e ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
877
878
879
880
881
		snprintf( textbuf, textlen,
			"objectClass \"%s\" only allowed in subentries",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
882

Kurt Zeilenga's avatar
Kurt Zeilenga committed
883
884
885
	return LDAP_SUCCESS;
}

886
887
888
889
890
891
892
static int dynamicObjectClass (
	Backend *be,
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
893
894
	*text = textbuf;

895
896
897
898
899
900
	if( !SLAP_DYNAMIC(be) ) {
		snprintf( textbuf, textlen,
			"objectClass \"%s\" not supported in context",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
901

902
903
904
	return LDAP_SUCCESS;
}

905
static int rootDseAttribute (
906
	Backend *be,
907
908
909
910
911
912
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
913

914
915
	if( e->e_nname.bv_len ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
916
			"attribute \"%s\" only allowed in the root DSE",
917
918
919
920
921
922
923
924
925
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	/* we should not be called for the root DSE */
	assert( 0 );
	return LDAP_SUCCESS;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
926
static int aliasAttribute (
927
	Backend *be,
928
929
930
931
932
933
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
934
935

	if( !SLAP_ALIASES(be) ) {
936
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
937
938
939
940
941
942
943
944
			"attribute \"%s\" not supported in context",
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	if( !is_entry_alias( e ) ) {
		snprintf( textbuf, textlen,
			"attribute \"%s\" only allowed in the alias",
945
946
947
948
949
950
951
952
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}

static int referralAttribute (
953
	Backend *be,
954
955
956
957
958
959
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
960
961
962
963
964
965
966
967

	if( !SLAP_REFERRALS(be) ) {
		snprintf( textbuf, textlen,
			"attribute \"%s\" not supported in context",
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

968
969
	if( !is_entry_referral( e ) ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
970
			"attribute \"%s\" only allowed in the referral",
971
972
973
974
975
976
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

static int subentryAttribute (
	Backend *be,
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;

	if( !SLAP_SUBENTRIES(be) ) {
		snprintf( textbuf, textlen,
			"attribute \"%s\" not supported in context",
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	if( !is_entry_subentry( e ) ) {
		snprintf( textbuf, textlen,
			"attribute \"%s\" only allowed in the subentry",
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}