schema_prep.c 25.7 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
	if( asserted == NULL ) {
38
		if( OID_LEADCHAR( *a->bv_val ) ) {
39
40
41
42
43
44
			/* OID form, return FALSE */
			*matchp = 1;
			return LDAP_SUCCESS;
		}

		/* desc form, return undefined */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
45
		return SLAPD_COMPARE_UNDEFINED;
46
47
48
	}

	if ( oc == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
49
50
		/* unrecognized stored value */
		return SLAPD_COMPARE_UNDEFINED;
51
52
	}

53
	if( SLAP_IS_MR_VALUE_SYNTAX_MATCH( flags ) ) {
54
55
56
57
58
		*matchp = ( asserted != oc );
	} else {
		*matchp = !is_object_subclass( asserted, oc );
	}

59
#if 0
60
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
61
62
63
	LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
		   "objectClassMatch(%s, %s) = %d\n",
		   value->bv_val, a->bv_val, *matchp ));
64
#else
65
66
	Debug( LDAP_DEBUG_TRACE, "objectClassMatch(%s,%s) = %d\n",
		value->bv_val, a->bv_val, *matchp );
67
#endif
68
69
#endif

70
71
72
73
74
75
	return LDAP_SUCCESS;
}

static int
structuralObjectClassMatch(
	int *matchp,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
76
	slap_mask_t flags,
77
78
79
80
81
82
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	struct berval *a = (struct berval *) assertedValue;
Howard Chu's avatar
Howard Chu committed
83
84
	ObjectClass *oc = oc_bvfind( value );
	ObjectClass *asserted = oc_bvfind( a );
85
86
87
88
89
90
91
92
93
94
95

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

97
98
99
100
101
102
103
104
	if ( oc == NULL ) {
		/* unrecognized stored value */
		return SLAPD_COMPARE_UNDEFINED;
	}

	*matchp = ( asserted != oc );

#if 0
105
#ifdef NEW_LOGGING
Gary Williams's avatar
Gary Williams committed
106
107
108
	LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
		   "structuralObjectClassMatch( %s, %s ) = %d\n",
		   value->bv_val, a->bv_val, *matchp ));
109
#else
110
111
	Debug( LDAP_DEBUG_TRACE, "structuralObjectClassMatch(%s,%s) = %d\n",
		value->bv_val, a->bv_val, *matchp );
112
#endif
113
#endif
114
115
116
117

	return LDAP_SUCCESS;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
118
119
120
static ObjectClassSchemaCheckFN rootDseObjectClass;
static ObjectClassSchemaCheckFN subentryObjectClass;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
121
static struct slap_schema_oc_map {
122
	char *ssom_name;
123
124
	char *ssom_defn;
	ObjectClassSchemaCheckFN *ssom_check;
125
126
	size_t ssom_offset;
} oc_map[] = {
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	{ "top", "( 2.5.6.0 NAME 'top' "
			"DESC 'top of the superclass chain' "
			"ABSTRACT MUST objectClass )",
		0, offsetof(struct slap_internal_schema, si_oc_top) },
	{ "extensibleObject", "( 1.3.6.1.4.1.1466.101.120.111 "
			"NAME 'extensibleObject' "
			"DESC 'RFC2252: extensible object' "
			"SUP top AUXILIARY )",
		0, offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
	{ "alias", "( 2.5.6.1 NAME 'alias' "
			"DESC 'RFC2256: an alias' "
			"SUP top STRUCTURAL "
			"MUST aliasedObjectName )",
		0, offsetof(struct slap_internal_schema, si_oc_alias) },
	{ "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
			"DESC 'namedref: named subordinate referral' "
			"SUP top STRUCTURAL MUST ref )",
		0, offsetof(struct slap_internal_schema, si_oc_referral) },
	{ "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
			"NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
			"DESC 'OpenLDAP Root DSE object' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
148
149
			"SUP top STRUCTURAL MAY cn )", rootDseObjectClass,
		offsetof(struct slap_internal_schema, si_oc_rootdse) },
150
151
152
153
154
155
	{ "subentry", "( 2.5.20.0 NAME 'subentry' "
			"SUP top STRUCTURAL "
			"MUST ( cn $ subtreeSpecification ) )",
		0, offsetof(struct slap_internal_schema, si_oc_subentry) },
	{ "subschema", "( 2.5.20.1 NAME 'subschema' "
		"DESC 'RFC2252: controlling subschema (sub)entry' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
156
		"AUXILIARY "
157
158
		"MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
			"objectClasses $ attributeTypes $ matchingRules $ "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
159
160
			"matchingRuleUse ) )", subentryObjectClass,
		offsetof(struct slap_internal_schema, si_oc_subschema) },
161
162
	{ "collectiveAttributes", "( 2.5.20.2 "
			"NAME 'collectiveAttributes' "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
163
			"AUXILIARY )", subentryObjectClass,
164
		offsetof(struct slap_internal_schema, si_oc_collectiveAttributes) },
165
166
167
168
169
170
	{ "dynamicObject", "( 1.3.6.1.4.1.1466.101.119.2 "
			"NAME 'dynamicObject' "
			"DESC 'RFC2589: Dynamic Object' "
			"SUP top AUXILIARY )",
		0,
		offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
171
172
173
	{ NULL, 0 }
};

174
175
176
177
static AttributeTypeSchemaCheckFN rootDseAttribute;
static AttributeTypeSchemaCheckFN subentryAttribute;
static AttributeTypeSchemaCheckFN referralAttribute;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
178
static struct slap_schema_ad_map {
179
	char *ssam_name;
180
181
	char *ssam_defn;
	AttributeTypeSchemaCheckFN *ssam_check;
182
	slap_mr_match_func *ssam_match;
183
184
	slap_mr_indexer_func *ssam_indexer;
	slap_mr_filter_func *ssam_filter;
185
186
	size_t ssam_offset;
} ad_map[] = {
187
188
189
190
191
	{ "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 )",
			NULL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
192
		objectClassMatch, NULL, NULL,
193
		offsetof(struct slap_internal_schema, si_ad_objectClass) },
194
195

	/* user entry operational attributes */
196
197
198
199
200
201
	{ "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 "
			"NO-USER-MODIFICATION SINGLE-VALUE USAGE directoryOperation )",
		NULL,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
202
		structuralObjectClassMatch, NULL, NULL,
203
		offsetof(struct slap_internal_schema, si_ad_structuralObjectClass) },
204
205
206
207
208
209
210
	{ "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 )",
		NULL, NULL, NULL, NULL,
211
		offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
212
213
214
215
216
217
218
	{ "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 )",
		NULL, NULL, NULL, NULL,
219
		offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	{ "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 )",
		NULL, NULL, NULL, NULL,
		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 )",
		NULL, NULL, NULL, NULL,
		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 )",
		NULL, NULL, NULL, NULL,
240
		offsetof(struct slap_internal_schema, si_ad_hasSubordinates) },
241
242
243
244
245
246
	{ "subschemaSubentry", "( 2.5.18.10 NAME 'subschemaSubentry' "
			"DESC 'RFC2252: name of controlling subschema entry' "
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
			"SINGLE-VALUE USAGE directoryOperation )",
		NULL, NULL, NULL, NULL,
247
		offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
248
249
	{ "collectiveAttributeSubentry", "( 2.5.18.12 "
			"NAME 'collectiveAttributeSubentry' "
250
251
252
253
254
255
256
257
258
259
260
			"EQUALITY distinguishedNameMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
			"USAGE directoryOperation NO-USER-MODIFICATION )",
		NULL, NULL, NULL, NULL,
		offsetof(struct slap_internal_schema, si_ad_collectiveSubentry) },
	{ "collectiveExclusions", "( 2.5.18.7 NAME 'collectiveExclusions' "
			"EQUALITY objectIdentifierMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
			"USAGE directoryOperation )",
		NULL, NULL, NULL, NULL,
		offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
	{ "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 )",
		NULL, NULL, NULL, NULL,
		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 )",
		NULL, NULL, NULL, NULL,
		offsetof(struct slap_internal_schema, si_ad_entryCSN) },

277
	/* root DSE attributes */
278
279
280
	{ "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 )",
281
		rootDseAttribute, NULL, NULL, NULL,
282
		offsetof(struct slap_internal_schema, si_ad_altServer) },
283
284
285
286
	{ "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 )",
287
		rootDseAttribute, NULL, NULL, NULL,
288
		offsetof(struct slap_internal_schema, si_ad_namingContexts) },
289
290
291
292
	{ "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
			"NAME 'supportedControl' "
		   "DESC 'RFC2252: supported controls' "
		   "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
293
		rootDseAttribute, NULL, NULL, NULL,
294
		offsetof(struct slap_internal_schema, si_ad_supportedControl) },
295
296
297
298
	{ "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 )",
299
		rootDseAttribute, NULL, NULL, NULL,
300
		offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
301
302
303
304
	{ "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 )",
305
		rootDseAttribute, NULL, NULL, NULL,
306
		offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
307
308
309
310
	{ "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 )",
311
		rootDseAttribute, NULL, NULL, NULL,
312
		offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
313
314
315
316
317
318
	{ "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 )",
319
		rootDseAttribute, NULL, NULL, NULL,
320
		offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
321
322
323
324
325
326
	{ "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 )",
327
		rootDseAttribute, NULL, NULL, NULL,
328
329
330
331
332
333
334
		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 )",
335
		rootDseAttribute, NULL, NULL, NULL,
336
337
338
339
340
341
342
343
344
345
346
347
348
		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 )",
		NULL, NULL, NULL, NULL,
		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 )",
349
		subentryAttribute, NULL, NULL, NULL,
350
		offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
351

352
	/* subschema subentry attributes */
353
354
355
356
357
	{ "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 ) ",
358
		subentryAttribute, NULL, NULL, NULL,
359
360
361
362
363
		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 )",
364
		subentryAttribute, NULL, NULL, NULL,
365
		offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
366
367
368
369
	{ "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 )",
370
		subentryAttribute, NULL, NULL, NULL,
371
		offsetof(struct slap_internal_schema, si_ad_matchingRules) },
372
373
374
375
	{ "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 )",
376
		subentryAttribute, NULL, NULL, NULL,
377
378
379
380
381
		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 )",
382
		subentryAttribute, NULL, NULL, NULL,
383
		offsetof(struct slap_internal_schema, si_ad_objectClasses) },
384
385
386
387
	{ "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 )",
388
		subentryAttribute, NULL, NULL, NULL,
389
		offsetof(struct slap_internal_schema, si_ad_nameForms) },
390
	{ "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
391
392
393
			"DESC 'RFC2252: matching rule uses' "
			"EQUALITY objectIdentifierFirstComponentMatch "
			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
394
		subentryAttribute, NULL, NULL, NULL,
395
		offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
396

397
398
399
400
	{ "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 )",
401
		subentryAttribute, NULL, NULL, NULL,
402
403
		offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },

404
	/* knowledge information */
405
406
407
408
409
410
	{ "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 )",
		NULL, NULL, NULL, NULL,
411
		offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
412
413
414
415
416
	{ "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 )",
417
		referralAttribute, NULL, NULL, NULL,
418
419
		offsetof(struct slap_internal_schema, si_ad_ref) },

Kurt Zeilenga's avatar
Kurt Zeilenga committed
420
	/* access control internals */
421
422
423
424
425
426
	{ "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 )",
		NULL, NULL, NULL, NULL,
427
		offsetof(struct slap_internal_schema, si_ad_entry) },
428
429
430
431
432
433
	{ "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 )",
		NULL, NULL, NULL, NULL,
434
		offsetof(struct slap_internal_schema, si_ad_children) },
435
#ifdef SLAPD_ACI_ENABLED
436
437
438
439
440
441
442
	{ "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 )",
		NULL, NULL, NULL, NULL,
443
444
		offsetof(struct slap_internal_schema, si_ad_aci) },
#endif
445

446
447
448
449
450
451
452
453
454
455
456
	{ "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 )",
		NULL, NULL, NULL, NULL,
		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 )",
457
		rootDseAttribute, NULL, NULL, NULL,
458
459
		offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },

460
	/* userApplication attributes */
461
462
463
464
465
466
	{ "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 )",
		NULL, NULL, NULL, NULL,
		offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
	{ "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} )",
		NULL, NULL, NULL, NULL,
		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 )",
		NULL, NULL, NULL, NULL,
		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} )",
		NULL, NULL, NULL, NULL,
485
		offsetof(struct slap_internal_schema, si_ad_userPassword) },
486
487

#ifdef SLAPD_AUTHPASSWD
488
489
490
491
492
493
494
495
496
497
498
499
500
	{ "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 )",
		NULL, NULL, NULL, NULL,
		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 )",
501
		subschemaAttribute, NULL, NULL, NULL,
502
		offsetof(struct slap_internal_schema, si_ad_authPassword) },
503
#endif
504
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
505
506
	{ "krbName", NULL,
		NULL, NULL, NULL, NULL,
507
508
509
		offsetof(struct slap_internal_schema, si_ad_krbName) },
#endif

510
	{ NULL, NULL, NULL, NULL, NULL, NULL, 0 }
511
512
};

513
514
515
static AttributeType slap_at_undefined = {
	{ "1.1.1", NULL, NULL, 1, NULL,
		NULL, NULL, NULL, NULL,
516
		0, 0, 0, 1, 3 }, /* LDAPAttributeType */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
517
	{ sizeof("UNDEFINED")-1, "UNDEFINED" }, /* cname */
518
519
520
521
	NULL, /* sup */
	NULL, /* subtypes */
	NULL, NULL, NULL, NULL,	/* matching rules */
	NULL, /* syntax (this may need to be defined) */
522
	(AttributeTypeSchemaCheckFN *) 0, /* schema check function */
523
	NULL, /* attribute description */
524
	NULL  /* next */
525
	/* mutex (don't know how to initialize it :) */
526
};
527

Kurt Zeilenga's avatar
Kurt Zeilenga committed
528
static struct slap_schema_mr_map {
529
530
531
532
533
534
535
536
537
538
	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
539
static struct slap_schema_syn_map {
540
541
542
543
544
545
546
547
548
549
	char *sssm_name;
	size_t sssm_offset;
} syn_map[] = {
	{ "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 }
};

550
int
551
552
slap_schema_load( void )
{
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
	int i;
	for( i=0; ad_map[i].ssam_name; i++ ) {
		if( ad_map[i].ssam_defn != NULL ) {
			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 );
		}
	}
586
587

	for( i=0; oc_map[i].ssom_name; i++ ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
588
589
590
591
		if( oc_map[i].ssom_defn != NULL ) {
			LDAPObjectClass *oc;
			int		code;
			const char	*err;
592

Kurt Zeilenga's avatar
Kurt Zeilenga committed
593
594
595
596
597
598
599
600
			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;
			}
601

Kurt Zeilenga's avatar
Kurt Zeilenga committed
602
603
604
605
606
607
			if ( oc->oc_oid == NULL ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: objectclass has no OID\n",
					oc_map[i].ssom_name );
				return LDAP_OTHER;
			}
608

Kurt Zeilenga's avatar
Kurt Zeilenga committed
609
610
611
612
613
614
615
616
617
618
			code = oc_add(oc,&err);
			if ( code ) {
				fprintf( stderr, "slap_schema_load: "
					"%s: %s: \"%s\"\n",
				 	oc_map[i].ssom_name, scherr2str(code), err);
				return code;
			}

			ldap_memfree(oc);
		}
619
620
	}

621
622
623
624
625
	return LDAP_SUCCESS;
}

int
slap_schema_check( void )
626
627
628
629
630
{
	int i;
	/* we should only be called once after schema_init() was called */
	assert( schema_init_done == 1 );

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

635
636
		assert( *synp == NULL );

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

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

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

651
652
		assert( *mrp == NULL );

653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
		*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;
		}
	}

	slap_at_undefined.sat_syntax = syn_find( SLAPD_OCTETSTRING_SYNTAX );
	if( slap_at_undefined.sat_syntax == NULL ) {
		fprintf( stderr, "slap_schema_check: "
			"No octetString syntax \"" SLAPD_OCTETSTRING_SYNTAX "\"\n" );
		return LDAP_INVALID_SYNTAX;
	}
	slap_schema.si_at_undefined = &slap_at_undefined;

671
672
673
674
675
676
677
	for( i=0; ad_map[i].ssam_name; i++ ) {
		int rc;
		const char *text;

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

678
		assert( *adp == NULL );
679
680
681
682

		rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );

		if( rc != LDAP_SUCCESS ) {
683
			fprintf( stderr, "slap_schema_check: "
684
685
686
687
688
689
690
691
692
693
694
				"No attribute \"%s\" defined in schema\n",
				ad_map[i].ssam_name );
			return rc;
		}

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

695
696
697
	for( i=0; oc_map[i].ssom_name; i++ ) {
		ObjectClass ** ocp = (ObjectClass **)
			&(((char *) &slap_schema)[oc_map[i].ssom_offset]);
698

699
700
		assert( *ocp == NULL );

701
		*ocp = oc_find( oc_map[i].ssom_name );
702

703
704
705
706
707
		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;
708
709
710
		}
	}

711
712
713
	++schema_init_done;
	return LDAP_SUCCESS;
}
714

Kurt Zeilenga's avatar
Kurt Zeilenga committed
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
static int rootDseObjectClass (
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
	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;
}

static int subentryObjectClass (
	Entry *e,
	ObjectClass *oc,
	const char** text,
	char *textbuf, size_t textlen )
{
	if( !is_entry_subentry( e ) ) {
		snprintf( textbuf, textlen,
			"objectClass \"%s\" only allowed in subentries",
			oc->soc_oid );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}
	return LDAP_SUCCESS;
}

749
750
751
752
753
754
755
756
757
static int rootDseAttribute (
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
	if( e->e_nname.bv_len ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
758
			"attribute \"%s\" only allowed in the root DSE",
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
			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;
}

static int subentryAttribute (
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
	if( !is_entry_subentry( e ) ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
777
			"attribute \"%s\" only allowed in the subentry",
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}

static int referralAttribute (
	Entry *e,
	Attribute *attr,
	const char** text,
	char *textbuf, size_t textlen )
{
	*text = textbuf;
	if( !is_entry_referral( e ) ) {
		snprintf( textbuf, textlen,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
794
			"attribute \"%s\" only allowed in the referral",
795
796
797
798
799
800
			attr->a_desc->ad_cname.bv_val );
		return LDAP_OBJECT_CLASS_VIOLATION;
	}

	return LDAP_SUCCESS;
}