schema_prep.c 35.2 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

int schema_init_done = 0;

struct slap_internal_schema slap_schema;

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
static int objectClassNormalize(
	slap_mask_t use,
	struct slap_syntax *syntax, /* NULL if in is asserted value */
	struct slap_matching_rule *mr,
	struct berval * in,
	struct berval * out )
{
	ObjectClass *oc = oc_bvfind( in );

	if( oc != NULL ) {
		ber_dupbv( out, &oc->soc_cname );
	} else {
		ber_dupbv( out, in );
	}

#if 0
#ifdef NEW_LOGGING
	LDAP_LOG( CONFIG, ENTRY, 
		"< objectClassNormalize(%s, %s)\n", in->bv_val, out->bv_val, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "< objectClassNormalize(%s,%s)\n",
		in->bv_val, out->bv_val, 0 );
#endif
#endif

	return LDAP_SUCCESS;
}

52
static int
53
objectSubClassMatch(
54
	int *matchp,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
55
	slap_mask_t flags,
56
57
58
59
60
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
61
	struct berval *a = (struct berval *) assertedValue;
Howard Chu's avatar
Howard Chu committed
62
63
	ObjectClass *oc = oc_bvfind( value );
	ObjectClass *asserted = oc_bvfind( a );
64

65
#if 0
66
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
67
	LDAP_LOG( CONFIG, ENTRY, 
68
		"> objectSubClassMatch(%s, %s)\n", value->bv_val, a->bv_val, 0 );
69
#else
70
	Debug( LDAP_DEBUG_TRACE, "> objectSubClassMatch(%s,%s)\n",
71
72
73
74
		value->bv_val, a->bv_val, 0 );
#endif
#endif

75
	if( asserted == NULL ) {
76
		if( OID_LEADCHAR( *a->bv_val ) ) {
77
78
79
80
81
82
			/* OID form, return FALSE */
			*matchp = 1;
			return LDAP_SUCCESS;
		}

		/* desc form, return undefined */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
83
		return SLAPD_COMPARE_UNDEFINED;
84
85
86
	}

	if ( oc == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
87
88
		/* unrecognized stored value */
		return SLAPD_COMPARE_UNDEFINED;
89
90
	}

91
	if( SLAP_IS_MR_VALUE_SYNTAX_MATCH( flags ) ) {
92
93
94
95
96
		*matchp = ( asserted != oc );
	} else {
		*matchp = !is_object_subclass( asserted, oc );
	}

97
#if 0
98
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
99
	LDAP_LOG( CONFIG, ENTRY, 
100
		"< objectSubClassMatch(%s, %s) = %d\n",
Julius Enarusai's avatar
   
Julius Enarusai committed
101
		value->bv_val, a->bv_val, *matchp );
102
#else
103
	Debug( LDAP_DEBUG_TRACE, "< objectSubClassMatch(%s,%s) = %d\n",
104
		value->bv_val, a->bv_val, *matchp );
105
#endif
106
107
#endif

108
109
110
	return LDAP_SUCCESS;
}

111
112
113
114
115
116
117
118
static int objectSubClassIndexer( 
	slap_mask_t use,
	slap_mask_t mask,
	struct slap_syntax *syntax,
	struct slap_matching_rule *mr,
	struct berval *prefix,
	BerVarray values,
	BerVarray *keysp )
119
{
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
	int rc, noc, i;
	BerVarray ocvalues;
	
	for( noc=0; values[noc].bv_val != NULL; noc++ ) {
#if 0
#ifdef NEW_LOGGING
		LDAP_LOG( CONFIG, ENTRY, 
			"> objectSubClassIndexer(%d, %s)\n",
			noc, values[noc].bv_val, 0 );
#else
		Debug( LDAP_DEBUG_TRACE,
			"> objectSubClassIndexer(%d, %s)\n",
			noc, values[noc].bv_val, 0 );
#endif
#endif
		/* just count em */;
	}

	/* over allocate */
	ocvalues = ch_malloc( sizeof( struct berval ) * (noc+16) );
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
	/* copy listed values (and termination) */
	AC_MEMCPY( ocvalues, values, sizeof( struct berval ) * noc+1 );

	/* expand values */
	for( i=0; i<noc; i++ ) {
		int j;
		ObjectClass *oc = oc_bvfind( &values[i] );
		if( oc == NULL || oc->soc_sups == NULL ) continue;
		
		for( j=0; oc->soc_sups[j] != NULL; j++ ) {
			int found = 0;
			ObjectClass *sup = oc->soc_sups[j];
			int k;

			for( k=0; k<noc; k++ ) {

#if 0
158
#ifdef NEW_LOGGING
159
160
161
				LDAP_LOG( CONFIG, ENTRY, 
					"= objectSubClassIndexer(%d, %s, %s)\n",
					k, ocvalues[k].bv_val, sup->soc_cname.bv_val );
162
#else
163
164
165
				Debug( LDAP_DEBUG_TRACE,
					"= objectSubClassIndexer(%d, %s, %s)\n",
					k, ocvalues[k].bv_val, sup->soc_cname.bv_val );
166
167
#endif
#endif
168
169
170
171
172
				if( ber_bvcmp( &ocvalues[k], &sup->soc_cname ) == 0 ) {
					found++;
					break;
				}
			}
173

174
175
176
			if( !found ) {
				ocvalues = ch_realloc( ocvalues,
					sizeof( struct berval ) * (noc+2) );
177

178
				assert( k == noc );
179

180
181
182
183
				ocvalues[noc] = sup->soc_cname;

				assert( ocvalues[noc].bv_val );
				assert( ocvalues[noc].bv_len );
184

185
				noc++;
186

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
				ocvalues[noc].bv_len = 0;
				ocvalues[noc].bv_val = NULL;

#if 0
#ifdef NEW_LOGGING
				LDAP_LOG( CONFIG, ENTRY, 
					"< objectSubClassIndexer(%d, %d, %s)\n",
					i, k, sup->soc_cname.bv_val );
#else
				Debug( LDAP_DEBUG_TRACE,
					"< objectSubClassIndexer(%d, %d, %s)\n",
					i, k, sup->soc_cname.bv_val );
#endif
#endif
			}
		}
	}

#if 0
206
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
207
	LDAP_LOG( CONFIG, ENTRY, 
208
		"< objectSubClassIndexer(%d)\n", noc, 0, 0 );
209
#else
210
211
	Debug( LDAP_DEBUG_TRACE, "< objectSubClassIndexer(%d)\n",
		noc, 0, 0 );
212
#endif
213
#endif
214

215
216
217
218
219
	rc = octetStringIndexer( use, mask, syntax, mr,
		prefix, ocvalues, keysp );

	ch_free( ocvalues );
	return rc;
220
}
221
222

#define objectSubClassFilter octetStringFilter
223

Kurt Zeilenga's avatar
Kurt Zeilenga committed
224
static ObjectClassSchemaCheckFN rootDseObjectClass;
225
226
static ObjectClassSchemaCheckFN aliasObjectClass;
static ObjectClassSchemaCheckFN referralObjectClass;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
227
static ObjectClassSchemaCheckFN subentryObjectClass;
228
static ObjectClassSchemaCheckFN dynamicObjectClass;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
229

Kurt Zeilenga's avatar
Kurt Zeilenga committed
230
static struct slap_schema_oc_map {
231
	char *ssom_name;
232
233
	char *ssom_defn;
	ObjectClassSchemaCheckFN *ssom_check;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
234
	slap_mask_t ssom_flags;
235
236
	size_t ssom_offset;
} oc_map[] = {
237
238
239
	{ "top", "( 2.5.6.0 NAME 'top' "
			"DESC 'top of the superclass chain' "
			"ABSTRACT MUST objectClass )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
240
		0, 0, offsetof(struct slap_internal_schema, si_oc_top) },
241
242
243
244
	{ "extensibleObject", "( 1.3.6.1.4.1.1466.101.120.111 "
			"NAME 'extensibleObject' "
			"DESC 'RFC2252: extensible object' "
			"SUP top AUXILIARY )",
245
246
		0, SLAP_OC_OPERATIONAL,
		offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
247
248
249
250
	{ "alias", "( 2.5.6.1 NAME 'alias' "
			"DESC 'RFC2256: an alias' "
			"SUP top STRUCTURAL "
			"MUST aliasedObjectName )",
251
		aliasObjectClass, SLAP_OC_ALIAS|SLAP_OC_OPERATIONAL,
252
		offsetof(struct slap_internal_schema, si_oc_alias) },
253
254
255
	{ "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
			"DESC 'namedref: named subordinate referral' "
			"SUP top STRUCTURAL MUST ref )",
256
		referralObjectClass, SLAP_OC_REFERRAL|SLAP_OC_OPERATIONAL,
257
		offsetof(struct slap_internal_schema, si_oc_referral) },
258
259
260
	{ "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
			"NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
			"DESC 'OpenLDAP Root DSE object' "
261
			"SUP top STRUCTURAL MAY cn )",
262
		rootDseObjectClass, SLAP_OC_OPERATIONAL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
263
		offsetof(struct slap_internal_schema, si_oc_rootdse) },
264
265
266
	{ "subentry", "( 2.5.20.0 NAME 'subentry' "
			"SUP top STRUCTURAL "
			"MUST ( cn $ subtreeSpecification ) )",
267
		subentryObjectClass, SLAP_OC_SUBENTRY|SLAP_OC_OPERATIONAL,
268
		offsetof(struct slap_internal_schema, si_oc_subentry) },
269
270
	{ "subschema", "( 2.5.20.1 NAME 'subschema' "
		"DESC 'RFC2252: controlling subschema (sub)entry' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
271
		"AUXILIARY "
272
273
		"MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
			"objectClasses $ attributeTypes $ matchingRules $ "
274
			"matchingRuleUse ) )",
275
		subentryObjectClass, SLAP_OC_OPERATIONAL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
276
		offsetof(struct slap_internal_schema, si_oc_subschema) },
277
278
279
280
	{ "monitor", "( 1.3.6.1.4.1.4203.666.3.2 NAME 'monitor' "
		"DESC 'OpenLDAP system monitoring' "
		"STRUCTURAL "
		"MUST cn )",
281
282
		0, SLAP_OC_OPERATIONAL,
		offsetof(struct slap_internal_schema, si_oc_monitor) },
283
284
	{ "collectiveAttributeSubentry", "( 2.5.20.2 "
			"NAME 'collectiveAttributeSubentry' "
285
			"AUXILIARY )",
286
287
		subentryObjectClass,
		SLAP_OC_COLLECTIVEATTRIBUTESUBENTRY|SLAP_OC_OPERATIONAL|SLAP_OC_HIDE,
288
		offsetof(struct slap_internal_schema, si_oc_collectiveAttributeSubentry) },
289
290
291
292
	{ "dynamicObject", "( 1.3.6.1.4.1.1466.101.119.2 "
			"NAME 'dynamicObject' "
			"DESC 'RFC2589: Dynamic Object' "
			"SUP top AUXILIARY )",
293
		dynamicObjectClass, SLAP_OC_DYNAMICOBJECT,
294
		offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
295
	{ NULL, NULL, NULL, 0, 0 }
296
297
};

298
static AttributeTypeSchemaCheckFN rootDseAttribute;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
299
static AttributeTypeSchemaCheckFN aliasAttribute;
300
static AttributeTypeSchemaCheckFN referralAttribute;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
301
static AttributeTypeSchemaCheckFN subentryAttribute;
302
static AttributeTypeSchemaCheckFN administrativeRoleAttribute;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
303
static AttributeTypeSchemaCheckFN dynamicAttribute;
304

Kurt Zeilenga's avatar
Kurt Zeilenga committed
305
static struct slap_schema_ad_map {
306
	char *ssam_name;
307
308
	char *ssam_defn;
	AttributeTypeSchemaCheckFN *ssam_check;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
309
	slap_mask_t ssam_flags;
310
311
	slap_mr_convert_func *ssam_convert;
	slap_mr_normalize_func *ssam_normalize;
312
	slap_mr_match_func *ssam_match;
313
314
	slap_mr_indexer_func *ssam_indexer;
	slap_mr_filter_func *ssam_filter;
315
316
	size_t ssam_offset;
} ad_map[] = {
317
318
319
320
	{ "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 )",
321
322
323
		NULL, SLAP_AT_FINAL,
		NULL, objectClassNormalize, objectSubClassMatch,
			objectSubClassIndexer, NULL,
324
		offsetof(struct slap_internal_schema, si_ad_objectClass) },
325
326

	/* user entry operational attributes */
327
328
329
330
	{ "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
331
			"SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
332
333
334
		NULL, 0,
		NULL, objectClassNormalize, objectSubClassMatch,
			objectSubClassIndexer, NULL,
335
		offsetof(struct slap_internal_schema, si_ad_structuralObjectClass) },
336
337
338
339
340
341
	{ "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 )",
342
343
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
344
		offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
345
346
347
348
349
350
	{ "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 )",
351
352
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
353
		offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
354
355
356
357
358
	{ "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 )",
359
360
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
361
362
363
364
365
366
		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 )",
367
368
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
369
370
371
372
373
374
		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 )",
375
376
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
377
		offsetof(struct slap_internal_schema, si_ad_hasSubordinates) },
378
379
380
	{ "subschemaSubentry", "( 2.5.18.10 NAME 'subschemaSubentry' "
			"DESC 'RFC2252: name of controlling subschema entry' "
			"EQUALITY distinguishedNameMatch "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
381
382
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE "
			"NO-USER-MODIFICATION USAGE directoryOperation )",
383
384
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
385
		offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
386
387
	{ "collectiveAttributeSubentries", "( 2.5.18.12 "
			"NAME 'collectiveAttributeSubentries' "
388
389
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
390
			"NO-USER-MODIFICATION USAGE directoryOperation )",
391
392
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
393
		offsetof(struct slap_internal_schema, si_ad_collectiveSubentries) },
394
395
396
397
	{ "collectiveExclusions", "( 2.5.18.7 NAME 'collectiveExclusions' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
			"USAGE directoryOperation )",
398
399
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
400
		offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
401

402
403
404
405
406
	{ "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 )",
407
408
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
409
410
411
412
413
414
		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 )",
415
416
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
417
418
		offsetof(struct slap_internal_schema, si_ad_entryCSN) },

419
	/* root DSE attributes */
420
421
422
	{ "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 )",
423
424
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
425
		offsetof(struct slap_internal_schema, si_ad_altServer) },
426
427
428
429
	{ "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 )",
430
431
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
432
		offsetof(struct slap_internal_schema, si_ad_namingContexts) },
433
434
	{ "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
			"NAME 'supportedControl' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
435
436
			"DESC 'RFC2252: supported controls' "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
437
438
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
439
		offsetof(struct slap_internal_schema, si_ad_supportedControl) },
440
441
442
443
	{ "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 )",
444
445
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
446
		offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
447
448
449
450
	{ "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 )",
451
452
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
453
		offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
454
455
456
457
	{ "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 )",
458
459
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
460
		offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
461
462
463
464
465
466
	{ "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 )",
467
468
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
469
		offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
470
471
472
473
474
475
476
	{ "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 )",
477
478
		rootDseAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
479
		offsetof(struct slap_internal_schema, si_ad_monitorContext) },
480
481
482
483
484
485
	{ "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 )",
486
487
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
488
489
490
491
492
493
494
		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 )",
495
496
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
497
498
499
500
501
502
503
		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 )",
504
505
		administrativeRoleAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
506
507
508
509
510
		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 )",
511
512
		subentryAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
513
		offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
514

515
	/* subschema subentry attributes */
516
517
518
519
520
	{ "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 ) ",
521
522
		subentryAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
523
524
525
526
527
		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 )",
528
529
		subentryAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
530
		offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
531
532
533
534
	{ "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 )",
535
536
		subentryAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
537
		offsetof(struct slap_internal_schema, si_ad_matchingRules) },
538
539
540
541
	{ "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 )",
542
543
		subentryAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
544
545
546
547
548
		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 )",
549
550
		subentryAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
551
		offsetof(struct slap_internal_schema, si_ad_objectClasses) },
552
553
554
555
	{ "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 )",
556
557
		subentryAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
558
		offsetof(struct slap_internal_schema, si_ad_nameForms) },
559
	{ "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
560
561
562
			"DESC 'RFC2252: matching rule uses' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
563
564
		subentryAttribute, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
565
		offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
566

567
568
569
570
	{ "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 )",
571
572
		subentryAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
573
574
		offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },

575
	/* knowledge information */
576
577
578
579
580
	{ "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 )",
581
582
		aliasAttribute, SLAP_AT_FINAL,
		NULL, NULL, NULL, NULL, NULL,
583
		offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
584
585
586
587
588
	{ "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 )",
589
590
		referralAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
591
592
		offsetof(struct slap_internal_schema, si_ad_ref) },

Kurt Zeilenga's avatar
Kurt Zeilenga committed
593
	/* access control internals */
594
595
596
597
598
	{ "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 )",
599
600
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
601
		offsetof(struct slap_internal_schema, si_ad_entry) },
602
603
604
605
606
	{ "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 )",
607
608
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
609
		offsetof(struct slap_internal_schema, si_ad_children) },
610
	{ "saslAuthzTo", "( 1.3.6.1.4.1.4203.666.1.8 "
611
612
613
614
			"NAME 'saslAuthzTo' "
			"DESC 'SASL proxy authorization targets' "
			"EQUALITY caseExactMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
615
			"USAGE distributedOperation )",
616
617
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
618
		offsetof(struct slap_internal_schema, si_ad_saslAuthzTo) },
619
	{ "saslAuthzFrom", "( 1.3.6.1.4.1.4203.666.1.9 "
620
621
622
623
			"NAME 'saslAuthzFrom' "
			"DESC 'SASL proxy authorization sources' "
			"EQUALITY caseExactMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
624
			"USAGE distributedOperation )",
625
626
		NULL, SLAP_AT_HIDE,
		NULL, NULL, NULL, NULL, NULL,
627
		offsetof(struct slap_internal_schema, si_ad_saslAuthzFrom) },
628
#ifdef SLAPD_ACI_ENABLED
629
630
631
632
633
634
	{ "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 )",
635
636
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
637
638
		offsetof(struct slap_internal_schema, si_ad_aci) },
#endif
639

640
641
642
643
	{ "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 )",
644
645
		dynamicAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
646
647
648
649
650
651
		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 )",
652
653
		rootDseAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
654
655
		offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },

656
	/* userApplication attributes (which system schema depends upon) */
657
658
659
660
	{ "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 )",
661
662
		NULL, SLAP_AT_ABSTRACT,
		NULL, NULL, NULL, NULL, NULL,
663
		offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
664
665
666
667
668
	{ "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} )",
669
670
		NULL, SLAP_AT_ABSTRACT,
		NULL, NULL, NULL, NULL, NULL,
671
672
673
674
		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 )",
675
676
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
677
678
679
680
681
		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} )",
682
683
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
684
		offsetof(struct slap_internal_schema, si_ad_userPassword) },
685
686

#ifdef SLAPD_AUTHPASSWD
687
688
689
690
691
	{ "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 )",
692
		NULL, 0,
693
		NULL, NULL, NULL, NULL, NULL,
694
695
696
697
698
699
700
		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 )",
701
702
		subschemaAttribute, 0,
		NULL, NULL, NULL, NULL, NULL,
703
		offsetof(struct slap_internal_schema, si_ad_authPassword) },
704
#endif
705
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
706
707
708
709
710
711
	{ "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 )",
712
713
		NULL, 0,
		NULL, NULL, NULL, NULL, NULL,
714
715
716
		offsetof(struct slap_internal_schema, si_ad_krbName) },
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
717
	{ NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
718
719
};

720
721
722
static AttributeType slap_at_undefined = {
	{ "1.1.1", NULL, NULL, 1, NULL,
		NULL, NULL, NULL, NULL,
723
		0, 0, 0, 1, 3 }, /* LDAPAttributeType */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
724
	{ sizeof("UNDEFINED")-1, "UNDEFINED" }, /* cname */
725
726
727
728
	NULL, /* sup */
	NULL, /* subtypes */
	NULL, NULL, NULL, NULL,	/* matching rules */
	NULL, /* syntax (this may need to be defined) */
729
730
	(AttributeTypeSchemaCheckFN *) 0, /* schema check function */
	SLAP_AT_ABSTRACT|SLAP_AT_FINAL,	/* mask */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
731
732
	NULL, /* next */
	NULL /* attribute description */
733
	/* mutex (don't know how to initialize it :) */
734
};
735

Kurt Zeilenga's avatar
Kurt Zeilenga committed
736
static struct slap_schema_mr_map {
737
738
739
740
741
742
743
744
745
746
	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
747
static struct slap_schema_syn_map {
748
749
750
	char *sssm_name;
	size_t sssm_offset;
} syn_map[] = {
751
752
	{ "1.3.6.1.4.1.1466.115.121.1.40",
		offsetof(struct slap_internal_schema, si_syn_octetString) },
753
754
755
756
757
758
759
	{ "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 }
};

760
int
761
762
slap_schema_load( void )
{
763
	int i;
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

	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;
		}
	}

797
	for( i=0; ad_map[i].ssam_name; i++ ) {
798
799
		assert( ad_map[i].ssam_defn != NULL );
		{
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
			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 );
		}
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
		{
			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;

853
854
855
856
857
858
859
860
861
			/* install custom rule routine */
			if( ad_map[i].ssam_convert ) {
				(*adp)->ad_type->sat_equality->smr_convert
					= ad_map[i].ssam_convert;
			}
			if( ad_map[i].ssam_normalize ) {
				(*adp)->ad_type->sat_equality->smr_normalize
					= ad_map[i].ssam_normalize;
			}
862
			if( ad_map[i].ssam_match ) {
863
864
865
866
867
868
869
870
871
872
				(*adp)->ad_type->sat_equality->smr_match
					= ad_map[i].ssam_match;
			}
			if( ad_map[i].ssam_indexer ) {
				(*adp)->ad_type->sat_equality->smr_indexer
					= ad_map[i].ssam_indexer;
			}
			if( ad_map[i].ssam_filter ) {
				(*adp)->ad_type->sat_equality->smr_filter
					= ad_map[i].ssam_filter;
873
874
			}
		}
875
	}
876
877

	for( i=0; oc_map[i].ssom_name; i++ ) {
878
879
		assert( oc_map[i].ssom_defn != NULL );
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
880
881
882
			LDAPObjectClass *oc;
			int		code;
			const char	*err;
883

Kurt Zeilenga's avatar
Kurt Zeilenga committed
884
885
886
887
888
889
890
891
			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;
			}
892

Kurt Zeilenga's avatar
Kurt Zeilenga committed
893
894
895
896
897
898
			if ( oc->oc_oid == NULL ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: objectclass has no OID\n",
					oc_map[i].ssom_name );
				return LDAP_OTHER;
			}
899

900
			code = oc_add(oc,0,&err);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
901
902
903
904
905
906
907
908
909
			if ( code ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: %s: \"%s\"\n",
				 	oc_map[i].ssom_name, scherr2str(code), err);
				return code;
			}

			ldap_memfree(oc);
		}
910
911
912
		{
			ObjectClass ** ocp = (ObjectClass **)
				&(((char *) &slap_schema)[oc_map[i].ssom_offset]);
913

914
			assert( *ocp == NULL );
915

916
917
918
919
920
921
922
			*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;
			}
923

924
925
926
927
928
929
			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;
930
931
932
		}
	}

933
	slap_at_undefined.sat_syntax = slap_schema.si_syn_distinguishedName;
934
935
	slap_schema.si_at_undefined = &slap_at_undefined;

936
937
	return LDAP_SUCCESS;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
938

939
940
941
942
943
int
slap_schema_check( void )
{
	/* we should only be called once after schema_init() was called */
	assert( schema_init_done == 1 );
944

945
946
947
	++schema_init_done;
	return LDAP_SUCCESS;
}
948

Kurt Zeilenga's avatar
Kurt Zeilenga committed
949
static int rootDseObjectClass (
950
	Backend *be,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
951
952
953
954
955
956
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
957

Kurt Zeilenga's avatar
Kurt Zeilenga committed
958
959
960
961
962
963
964
965
966
967
968
969
	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;
}

970
971
972
973
974
975
976
static int aliasObjectClass (
	Backend *be,
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
977
978
	*text = textbuf;

979
980
981
982
983
984
	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
985

986
987
988
989
990
991
992
993
994
995
	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
996
997
	*text = textbuf;

998
999
1000
1001
1002
1003
	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
1004

1005
1006
1007
	return LDAP_SUCCESS;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1008
static int subentryObjectClass (
1009
	Backend *be,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1010
1011
1012
1013
1014
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1015
1016
	*text = textbuf;

1017
1018
1019
1020
1021
1022
1023
1024
	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
1025
1026
1027
1028
1029
		snprintf( textbuf, textlen,
			"objectClass \"%s\" only allowed in subentries",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1030

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1031
1032
1033
	return LDAP_SUCCESS;
}

1034
1035
1036
1037
1038
1039
1040
static int dynamicObjectClass (
	Backend *be,
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1041
1042
	*text = textbuf;

1043
1044
1045
1046
1047
1048
	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
1049

1050
1051
1052
	return LDAP_SUCCESS;
}

1053
static int rootDseAttribute (
1054
	Backend *be,
1055
1056
1057
1058
1059
1060
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1061

1062
1063
	if( e->e_nname.bv_len ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1064
			"attribute \"%s\" only allowed in the root DSE",
1065
1066
1067
1068
1069
1070
1071
1072
1073
			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
1074
static int aliasAttribute (
1075
	Backend *be,
1076
1077
1078
1079
1080
1081
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1082
1083

	if( !SLAP_ALIASES(be) ) {
1084
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1085
1086
1087
1088
1089
1090
1091
1092
			"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",
1093
1094
1095
1096
1097
1098
1099
1100
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}

static int referralAttribute (
1101
	Backend *be,
1102
1103
1104
1105
1106
1107
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1108
1109
1110
1111
1112
1113
1114
1115

	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;
	}

1116
1117
	if( !is_entry_referral( e ) ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1118
			"attribute \"%s\" only allowed in the referral",
1119
1120
1121
1122
1123
1124
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

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;
	}

	return LDAP_SUCCESS;
}

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
static int administrativeRoleAttribute (
	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;
	}

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

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
static int dynamicAttribute (
	Backend *be,
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;

	if( !SLAP_DYNAMIC(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_dynamicObject( e ) ) {
		snprintf( textbuf, textlen,
			"attribute \"%s\" only allowed in dynamic object",
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}