]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_prep.c
Clean up last patch
[openldap] / servers / slapd / schema_prep.c
1 /* schema_init.c - init builtin schema */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include "slap.h"
17 #include "ldap_pvt.h"
18 #include "ldap_pvt_uc.h"
19
20 int schema_init_done = 0;
21
22 struct slap_internal_schema slap_schema;
23
24 static int
25 objectClassMatch(
26         int *matchp,
27         slap_mask_t flags,
28         Syntax *syntax,
29         MatchingRule *mr,
30         struct berval *value,
31         void *assertedValue )
32 {
33         struct berval *a = (struct berval *) assertedValue;
34         ObjectClass *oc = oc_bvfind( value );
35         ObjectClass *asserted = oc_bvfind( a );
36
37         if( asserted == NULL ) {
38                 if( OID_LEADCHAR( *a->bv_val ) ) {
39                         /* OID form, return FALSE */
40                         *matchp = 1;
41                         return LDAP_SUCCESS;
42                 }
43
44                 /* desc form, return undefined */
45                 return SLAPD_COMPARE_UNDEFINED;
46         }
47
48         if ( oc == NULL ) {
49                 /* unrecognized stored value */
50                 return SLAPD_COMPARE_UNDEFINED;
51         }
52
53         if( SLAP_IS_MR_VALUE_SYNTAX_MATCH( flags ) ) {
54                 *matchp = ( asserted != oc );
55         } else {
56                 *matchp = !is_object_subclass( asserted, oc );
57         }
58
59 #if 0
60 #ifdef NEW_LOGGING
61         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
62                    "objectClassMatch(%s, %s) = %d\n",
63                    value->bv_val, a->bv_val, *matchp ));
64 #else
65         Debug( LDAP_DEBUG_TRACE, "objectClassMatch(%s,%s) = %d\n",
66                 value->bv_val, a->bv_val, *matchp );
67 #endif
68 #endif
69
70         return LDAP_SUCCESS;
71 }
72
73 static int
74 structuralObjectClassMatch(
75         int *matchp,
76         slap_mask_t flags,
77         Syntax *syntax,
78         MatchingRule *mr,
79         struct berval *value,
80         void *assertedValue )
81 {
82         struct berval *a = (struct berval *) assertedValue;
83         ObjectClass *oc = oc_bvfind( value );
84         ObjectClass *asserted = oc_bvfind( a );
85
86         if( asserted == NULL ) {
87                 if( OID_LEADCHAR( *a->bv_val ) ) {
88                         /* OID form, return FALSE */
89                         *matchp = 1;
90                         return LDAP_SUCCESS;
91                 }
92
93                 /* desc form, return undefined */
94                 return SLAPD_COMPARE_UNDEFINED;
95         }
96
97         if ( oc == NULL ) {
98                 /* unrecognized stored value */
99                 return SLAPD_COMPARE_UNDEFINED;
100         }
101
102         *matchp = ( asserted != oc );
103
104 #if 0
105 #ifdef NEW_LOGGING
106         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
107                    "structuralObjectClassMatch( %s, %s ) = %d\n",
108                    value->bv_val, a->bv_val, *matchp ));
109 #else
110         Debug( LDAP_DEBUG_TRACE, "structuralObjectClassMatch(%s,%s) = %d\n",
111                 value->bv_val, a->bv_val, *matchp );
112 #endif
113 #endif
114
115         return LDAP_SUCCESS;
116 }
117
118 static ObjectClassSchemaCheckFN rootDseObjectClass;
119 static ObjectClassSchemaCheckFN aliasObjectClass;
120 static ObjectClassSchemaCheckFN referralObjectClass;
121 static ObjectClassSchemaCheckFN subentryObjectClass;
122 static ObjectClassSchemaCheckFN dynamicObjectClass;
123
124 static struct slap_schema_oc_map {
125         char *ssom_name;
126         char *ssom_defn;
127         ObjectClassSchemaCheckFN *ssom_check;
128         slap_mask_t ssom_flags;
129         size_t ssom_offset;
130 } oc_map[] = {
131         { "top", "( 2.5.6.0 NAME 'top' "
132                         "DESC 'top of the superclass chain' "
133                         "ABSTRACT MUST objectClass )",
134                 0, 0, offsetof(struct slap_internal_schema, si_oc_top) },
135         { "extensibleObject", "( 1.3.6.1.4.1.1466.101.120.111 "
136                         "NAME 'extensibleObject' "
137                         "DESC 'RFC2252: extensible object' "
138                         "SUP top AUXILIARY )",
139                 0, 0, offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
140         { "alias", "( 2.5.6.1 NAME 'alias' "
141                         "DESC 'RFC2256: an alias' "
142                         "SUP top STRUCTURAL "
143                         "MUST aliasedObjectName )",
144                 aliasObjectClass, 0,
145                 offsetof(struct slap_internal_schema, si_oc_alias) },
146         { "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
147                         "DESC 'namedref: named subordinate referral' "
148                         "SUP top STRUCTURAL MUST ref )",
149                 referralObjectClass, 0,
150                 offsetof(struct slap_internal_schema, si_oc_referral) },
151         { "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
152                         "NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
153                         "DESC 'OpenLDAP Root DSE object' "
154                         "SUP top STRUCTURAL MAY cn )",
155                 rootDseObjectClass, 0,
156                 offsetof(struct slap_internal_schema, si_oc_rootdse) },
157         { "subentry", "( 2.5.20.0 NAME 'subentry' "
158                         "SUP top STRUCTURAL "
159                         "MUST ( cn $ subtreeSpecification ) )",
160                 subentryObjectClass, 0,
161                 offsetof(struct slap_internal_schema, si_oc_subentry) },
162         { "subschema", "( 2.5.20.1 NAME 'subschema' "
163                 "DESC 'RFC2252: controlling subschema (sub)entry' "
164                 "AUXILIARY "
165                 "MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
166                         "objectClasses $ attributeTypes $ matchingRules $ "
167                         "matchingRuleUse ) )",
168                 subentryObjectClass,
169                 offsetof(struct slap_internal_schema, si_oc_subschema) },
170         { "monitor", "( 1.3.6.1.4.1.4203.666.3.2 NAME 'monitor' "
171                 "DESC 'OpenLDAP system monitoring' "
172                 "STRUCTURAL "
173                 "MUST cn )",
174                 0, 0, offsetof(struct slap_internal_schema, si_oc_monitor) },
175         { "collectiveAttributes", "( 2.5.20.2 "
176                         "NAME 'collectiveAttributes' "
177                         "AUXILIARY )",
178                 subentryObjectClass, 0,
179                 offsetof(struct slap_internal_schema, si_oc_collectiveAttributes) },
180         { "dynamicObject", "( 1.3.6.1.4.1.1466.101.119.2 "
181                         "NAME 'dynamicObject' "
182                         "DESC 'RFC2589: Dynamic Object' "
183                         "SUP top AUXILIARY )",
184                 dynamicObjectClass, 0,
185                 offsetof(struct slap_internal_schema, si_oc_dynamicObject) },
186         { NULL, NULL, NULL, 0, 0 }
187 };
188
189 static AttributeTypeSchemaCheckFN rootDseAttribute;
190 static AttributeTypeSchemaCheckFN aliasAttribute;
191 static AttributeTypeSchemaCheckFN referralAttribute;
192 static AttributeTypeSchemaCheckFN subentryAttribute;
193 static AttributeTypeSchemaCheckFN dynamicAttribute;
194
195 static struct slap_schema_ad_map {
196         char *ssam_name;
197         char *ssam_defn;
198         AttributeTypeSchemaCheckFN *ssam_check;
199         slap_mask_t ssam_flags;
200         slap_mr_match_func *ssam_match;
201         slap_mr_indexer_func *ssam_indexer;
202         slap_mr_filter_func *ssam_filter;
203         size_t ssam_offset;
204 } ad_map[] = {
205         { "objectClass", "( 2.5.4.0 NAME 'objectClass' "
206                         "DESC 'RFC2256: object classes of the entity' "
207                         "EQUALITY objectIdentifierMatch "
208                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
209                 NULL, 0,
210                 objectClassMatch, NULL, NULL,
211                 offsetof(struct slap_internal_schema, si_ad_objectClass) },
212
213         /* user entry operational attributes */
214         { "structuralObjectClass", "( 2.5.21.9 NAME 'structuralObjectClass' "
215                         "DESC 'X.500(93): structural object class of entry' "
216                         "EQUALITY objectIdentifierMatch "
217                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
218                         "NO-USER-MODIFICATION SINGLE-VALUE USAGE directoryOperation )",
219                 NULL, 0, structuralObjectClassMatch, NULL, NULL,
220                 offsetof(struct slap_internal_schema, si_ad_structuralObjectClass) },
221         { "createTimestamp", "( 2.5.18.1 NAME 'createTimestamp' "
222                         "DESC 'RFC2252: time which object was created' "
223                         "EQUALITY generalizedTimeMatch "
224                         "ORDERING generalizedTimeOrderingMatch "
225                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
226                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
227                 NULL, 0, NULL, NULL, NULL,
228                 offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
229         { "modifyTimestamp", "( 2.5.18.2 NAME 'modifyTimestamp' "
230                         "DESC 'RFC2252: time which object was last modified' "
231                         "EQUALITY generalizedTimeMatch "
232                         "ORDERING generalizedTimeOrderingMatch "
233                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
234                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
235                 NULL, 0, NULL, NULL, NULL,
236                 offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
237         { "creatorsName", "( 2.5.18.3 NAME 'creatorsName' "
238                         "DESC 'RFC2252: name of creator' "
239                         "EQUALITY distinguishedNameMatch "
240                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
241                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
242                 NULL, 0, NULL, NULL, NULL,
243                 offsetof(struct slap_internal_schema, si_ad_creatorsName) },
244         { "modifiersName", "( 2.5.18.4 NAME 'modifiersName' "
245                         "DESC 'RFC2252: name of last modifier' "
246                         "EQUALITY distinguishedNameMatch "
247                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
248                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
249                 NULL, 0, NULL, NULL, NULL,
250                 offsetof(struct slap_internal_schema, si_ad_modifiersName) },
251         { "hasSubordinates", "( 2.5.18.9 NAME 'hasSubordinates' "
252                         "DESC 'X.501: entry has children' "
253                         "EQUALITY booleanMatch "
254                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
255                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
256                 NULL, 0, NULL, NULL, NULL,
257                 offsetof(struct slap_internal_schema, si_ad_hasSubordinates) },
258         { "subschemaSubentry", "( 2.5.18.10 NAME 'subschemaSubentry' "
259                         "DESC 'RFC2252: name of controlling subschema entry' "
260                         "EQUALITY distinguishedNameMatch "
261                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
262                         "SINGLE-VALUE USAGE directoryOperation )",
263                 NULL, 0, NULL, NULL, NULL,
264                 offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
265         { "collectiveAttributeSubentry", "( 2.5.18.12 "
266                         "NAME 'collectiveAttributeSubentry' "
267                         "EQUALITY distinguishedNameMatch "
268                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
269                         "USAGE directoryOperation NO-USER-MODIFICATION )",
270                 NULL, 0, NULL, NULL, NULL,
271                 offsetof(struct slap_internal_schema, si_ad_collectiveSubentry) },
272         { "collectiveExclusions", "( 2.5.18.7 NAME 'collectiveExclusions' "
273                         "EQUALITY objectIdentifierMatch "
274                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
275                         "USAGE directoryOperation )",
276                 NULL, 0, NULL, NULL, NULL,
277                 offsetof(struct slap_internal_schema, si_ad_collectiveExclusions) },
278
279         { "entryUUID", "( 1.3.6.1.4.1.4203.666.1.6 NAME 'entryUUID' "   
280                         "DESC 'LCUP/LDUP: universally unique identifier' "
281                         "EQUALITY octetStringMatch "
282                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
283                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
284                 NULL, 0, NULL, NULL, NULL,
285                 offsetof(struct slap_internal_schema, si_ad_entryUUID) },
286         { "entryCSN", "( 1.3.6.1.4.1.4203.666.1.7 NAME 'entryCSN' "
287                         "DESC 'LCUP/LDUP: change sequence number' "
288                         "EQUALITY octetStringMatch "
289                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "
290                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
291                 NULL, 0, NULL, NULL, NULL,
292                 offsetof(struct slap_internal_schema, si_ad_entryCSN) },
293
294         /* root DSE attributes */
295         { "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' "
296                         "DESC 'RFC2252: alternative servers' "
297                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )",
298                 rootDseAttribute, 0, NULL, NULL, NULL,
299                 offsetof(struct slap_internal_schema, si_ad_altServer) },
300         { "namingContexts", "( 1.3.6.1.4.1.1466.101.120.5 "
301                         "NAME 'namingContexts' "
302                         "DESC 'RFC2252: naming contexts' "
303                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )",
304                 rootDseAttribute, 0, NULL, NULL, NULL,
305                 offsetof(struct slap_internal_schema, si_ad_namingContexts) },
306         { "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
307                         "NAME 'supportedControl' "
308                    "DESC 'RFC2252: supported controls' "
309                    "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
310                 rootDseAttribute, 0, NULL, NULL, NULL,
311                 offsetof(struct slap_internal_schema, si_ad_supportedControl) },
312         { "supportedExtension", "( 1.3.6.1.4.1.1466.101.120.7 "
313                         "NAME 'supportedExtension' "
314                         "DESC 'RFC2252: supported extended operations' "
315                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
316                 rootDseAttribute, 0, NULL, NULL, NULL,
317                 offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
318         { "supportedLDAPVersion", "( 1.3.6.1.4.1.1466.101.120.15 "
319                         "NAME 'supportedLDAPVersion' "
320                         "DESC 'RFC2252: supported LDAP versions' "
321                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )",
322                 rootDseAttribute, 0, NULL, NULL, NULL,
323                 offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
324         { "supportedSASLMechanisms", "( 1.3.6.1.4.1.1466.101.120.14 "
325                         "NAME 'supportedSASLMechanisms' "
326                         "DESC 'RFC2252: supported SASL mechanisms'"
327                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )",
328                 rootDseAttribute, 0, NULL, NULL, NULL,
329                 offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
330         { "supportedFeatures", "( 1.3.6.1.4.1.4203.1.3.5 "
331                         "NAME 'supportedFeatures' "
332                         "DESC 'features supported by the server' "
333                         "EQUALITY objectIdentifierMatch "
334                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
335                         "USAGE dSAOperation )",
336                 rootDseAttribute, 0, NULL, NULL, NULL,
337                 offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
338         { "vendorName", "( 1.3.6.1.1.4 NAME 'vendorName' "
339                         "DESC 'RFC3045: name of implementation vendor' "
340                         "EQUALITY 1.3.6.1.4.1.1466.109.114.1 "
341                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
342                         "SINGLE-VALUE NO-USER-MODIFICATION "
343                         "USAGE dSAOperation )",
344                 rootDseAttribute, 0, NULL, NULL, NULL,
345                 offsetof(struct slap_internal_schema, si_ad_vendorName) },
346         { "vendorVersion", "( 1.3.6.1.1.5 NAME 'vendorVersion' "
347                         "DESC 'RFC3045: version of implementation' "
348                         "EQUALITY 1.3.6.1.4.1.1466.109.114.1 "
349                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
350                         "SINGLE-VALUE NO-USER-MODIFICATION "
351                         "USAGE dSAOperation )",
352                 rootDseAttribute, 0, NULL, NULL, NULL,
353                 offsetof(struct slap_internal_schema, si_ad_vendorVersion) },
354
355         /* subentry attributes */
356         { "administrativeRole", "( 2.5.18.5 NAME 'administrativeRole' "
357                         "EQUALITY objectIdentifierMatch "
358                         "USAGE directoryOperation "
359                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
360                 NULL, 0, NULL, NULL, NULL,
361                 offsetof(struct slap_internal_schema, si_ad_administrativeRole) },
362         { "subtreeSpecification", "( 2.5.18.6 NAME 'subtreeSpecification' "
363                         "SINGLE-VALUE "
364                         "USAGE directoryOperation "
365                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.45 )",
366                 subentryAttribute, 0, NULL, NULL, NULL,
367                 offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
368
369         /* subschema subentry attributes */
370         { "ditStructureRules", "( 2.5.21.1 NAME 'dITStructureRules' "
371                         "DESC 'RFC2252: DIT structure rules' "
372                         "EQUALITY integerFirstComponentMatch "
373                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 "
374                         "USAGE directoryOperation ) ",
375                 subentryAttribute, 0, NULL, NULL, NULL,
376                 offsetof(struct slap_internal_schema, si_ad_ditStructureRules) },
377         { "ditContentRules", "( 2.5.21.2 NAME 'dITContentRules' "
378                         "DESC 'RFC2252: DIT content rules' "
379                         "EQUALITY objectIdentifierFirstComponentMatch "
380                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )",
381                 subentryAttribute, 0, NULL, NULL, NULL,
382                 offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
383         { "matchingRules", "( 2.5.21.4 NAME 'matchingRules' "
384                         "DESC 'RFC2252: matching rules' "
385                         "EQUALITY objectIdentifierFirstComponentMatch "
386                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )",
387                 subentryAttribute, 0, NULL, NULL, NULL,
388                 offsetof(struct slap_internal_schema, si_ad_matchingRules) },
389         { "attributeTypes", "( 2.5.21.5 NAME 'attributeTypes' "
390                         "DESC 'RFC2252: attribute types' "
391                         "EQUALITY objectIdentifierFirstComponentMatch "
392                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )",
393                 subentryAttribute, 0, NULL, NULL, NULL,
394                 offsetof(struct slap_internal_schema, si_ad_attributeTypes) },
395         { "objectClasses", "( 2.5.21.6 NAME 'objectClasses' "
396                         "DESC 'RFC2252: object classes' "
397                         "EQUALITY objectIdentifierFirstComponentMatch "
398                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )",
399                 subentryAttribute, 0, NULL, NULL, NULL,
400                 offsetof(struct slap_internal_schema, si_ad_objectClasses) },
401         { "nameForms", "( 2.5.21.7 NAME 'nameForms' "
402                         "DESC 'RFC2252: name forms ' "
403                         "EQUALITY objectIdentifierFirstComponentMatch "
404                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )",
405                 subentryAttribute, 0, NULL, NULL, NULL,
406                 offsetof(struct slap_internal_schema, si_ad_nameForms) },
407         { "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
408                         "DESC 'RFC2252: matching rule uses' "
409                         "EQUALITY objectIdentifierFirstComponentMatch "
410                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
411                 subentryAttribute, 0, NULL, NULL, NULL,
412                 offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
413
414         { "ldapSyntaxes", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' "
415                         "DESC 'RFC2252: LDAP syntaxes' "
416                         "EQUALITY objectIdentifierFirstComponentMatch "
417                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )",
418                 subentryAttribute, 0, NULL, NULL, NULL,
419                 offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },
420
421         /* knowledge information */
422         { "aliasedObjectName", "( 2.5.4.1 "
423                         "NAME ( 'aliasedObjectName' 'aliasedEntryName' ) "
424                         "DESC 'RFC2256: name of aliased object' "
425                         "EQUALITY distinguishedNameMatch "
426                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
427                 aliasAttribute, 0, NULL, NULL, NULL,
428                 offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
429         { "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
430                         "DESC 'namedref: subordinate referral URL' "
431                         "EQUALITY caseExactMatch "
432                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
433                         "USAGE distributedOperation )",
434                 referralAttribute, 0, NULL, NULL, NULL,
435                 offsetof(struct slap_internal_schema, si_ad_ref) },
436
437         /* access control internals */
438         { "entry", "( 1.3.6.1.4.1.4203.1.3.1 "
439                         "NAME 'entry' "
440                         "DESC 'OpenLDAP ACL entry pseudo-attribute' "
441                         "SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
442                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
443                 NULL, 0, NULL, NULL, NULL,
444                 offsetof(struct slap_internal_schema, si_ad_entry) },
445         { "children", "( 1.3.6.1.4.1.4203.1.3.2 "
446                         "NAME 'children' "
447                         "DESC 'OpenLDAP ACL children pseudo-attribute' "
448                         "SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
449                         "SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
450                 NULL, 0, NULL, NULL, NULL,
451                 offsetof(struct slap_internal_schema, si_ad_children) },
452 #ifdef SLAPD_ACI_ENABLED
453         { "OpenLDAPaci", "( 1.3.6.1.4.1.4203.666.1.5 "
454                         "NAME 'OpenLDAPaci' "
455                         "DESC 'OpenLDAP access control information (experimental)' "
456                         "EQUALITY OpenLDAPaciMatch "
457                         "SYNTAX 1.3.6.1.4.1.4203.666.2.1 "
458                         "USAGE directoryOperation )",
459                 NULL, 0, NULL, NULL, NULL,
460                 offsetof(struct slap_internal_schema, si_ad_aci) },
461 #endif
462
463         { "entryTtl", "( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl' "
464                         "DESC 'RFC2589: entry time-to-live' "
465                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE "
466                         "NO-USER-MODIFICATION USAGE dSAOperation )",
467                 dynamicAttribute, 0, NULL, NULL, NULL,
468                 offsetof(struct slap_internal_schema, si_ad_entryTtl) },
469         { "dynamicSubtrees", "( 1.3.6.1.4.1.1466.101.119.4 "
470                         "NAME 'dynamicSubtrees' "
471                         "DESC 'RFC2589: dynamic subtrees' "
472                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
473                         "USAGE dSAOperation )",
474                 rootDseAttribute, 0, NULL, NULL, NULL,
475                 offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },
476
477         /* userApplication attributes (which system schema depends upon) */
478         { "distinguishedName", "( 2.5.4.49 NAME 'distinguishedName' "
479                         "DESC 'RFC2256: common supertype of DN attributes' "
480                         "EQUALITY distinguishedNameMatch "
481                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
482                 NULL, 0, NULL, NULL, NULL,
483                 offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
484         { "name", "( 2.5.4.41 NAME 'name' "
485                         "DESC 'RFC2256: common supertype of name attributes' "
486                         "EQUALITY caseIgnoreMatch "
487                         "SUBSTR caseIgnoreSubstringsMatch "
488                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )",
489                 NULL, 0, NULL, NULL, NULL,
490                 offsetof(struct slap_internal_schema, si_ad_name) },
491         { "cn", "( 2.5.4.3 NAME ( 'cn' 'commonName' ) "
492                         "DESC 'RFC2256: common name(s) for which the entity is known by' "
493                         "SUP name )",
494                 NULL, 0, NULL, NULL, NULL,
495                 offsetof(struct slap_internal_schema, si_ad_cn) },
496         { "userPassword", "( 2.5.4.35 NAME 'userPassword' "
497                         "DESC 'RFC2256/2307: password of user' "
498                         "EQUALITY octetStringMatch "
499                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )",
500                 NULL, 0, NULL, NULL, NULL,
501                 offsetof(struct slap_internal_schema, si_ad_userPassword) },
502
503 #ifdef SLAPD_AUTHPASSWD
504         { "authPassword", "( 1.3.6.1.4.1.4203.1.3.4 "
505                         "NAME 'authPassword' "
506                         "DESC 'RFC3112: authentication password attribute' "
507                         "EQUALITY 1.3.6.1.4.1.4203.1.2.2 "
508                         "SYNTAX 1.3.6.1.4.1.4203.1.1.2 )",
509                 NULL, 0,
510                 NULL, NULL, NULL,
511                 offsetof(struct slap_internal_schema, si_ad_authPassword) },
512         { "supportedAuthPasswordSchemes", "( 1.3.6.1.4.1.4203.1.3.3 "
513                         "NAME 'supportedAuthPasswordSchemes' "
514                         "DESC 'RFC3112: supported authPassword schemes' "
515                         "EQUALITY caseExactIA5Match "
516                         "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} "
517                         "USAGE dSAOperation )",
518                 subschemaAttribute, 0, NULL, NULL, NULL,
519                 offsetof(struct slap_internal_schema, si_ad_authPassword) },
520 #endif
521 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
522         { "krbName", NULL,
523                 NULL, 0, NULL, NULL, NULL,
524                 offsetof(struct slap_internal_schema, si_ad_krbName) },
525 #endif
526
527         { NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
528 };
529
530 static AttributeType slap_at_undefined = {
531         { "1.1.1", NULL, NULL, 1, NULL,
532                 NULL, NULL, NULL, NULL,
533                 0, 0, 0, 1, 3 }, /* LDAPAttributeType */
534         { sizeof("UNDEFINED")-1, "UNDEFINED" }, /* cname */
535         NULL, /* sup */
536         NULL, /* subtypes */
537         NULL, NULL, NULL, NULL, /* matching rules */
538         NULL, /* syntax (this may need to be defined) */
539         (AttributeTypeSchemaCheckFN *) 0, 0, /* schema check function/mask */
540         NULL  /* next */
541         NULL, /* attribute description */
542         /* mutex (don't know how to initialize it :) */
543 };
544
545 static struct slap_schema_mr_map {
546         char *ssmm_name;
547         size_t ssmm_offset;
548 } mr_map[] = {
549         { "distinguishedNameMatch",
550                 offsetof(struct slap_internal_schema, si_mr_distinguishedNameMatch) },
551         { "integerMatch",
552                 offsetof(struct slap_internal_schema, si_mr_integerMatch) },
553         { NULL, 0 }
554 };
555
556 static struct slap_schema_syn_map {
557         char *sssm_name;
558         size_t sssm_offset;
559 } syn_map[] = {
560         { "1.3.6.1.4.1.1466.115.121.1.12",
561                 offsetof(struct slap_internal_schema, si_syn_distinguishedName) },
562         { "1.3.6.1.4.1.1466.115.121.1.27",
563                 offsetof(struct slap_internal_schema, si_syn_integer) },
564         { NULL, 0 }
565 };
566
567 int
568 slap_schema_load( void )
569 {
570         int i;
571         for( i=0; ad_map[i].ssam_name; i++ ) {
572                 if( ad_map[i].ssam_defn != NULL ) {
573                         LDAPAttributeType *at;
574                         int             code;
575                         const char      *err;
576
577                         at = ldap_str2attributetype( ad_map[i].ssam_defn,
578                                 &code, &err, LDAP_SCHEMA_ALLOW_ALL );
579                         if ( !at ) {
580                                 fprintf( stderr,
581                                         "slap_schema_load: %s: %s before %s\n",
582                                          ad_map[i].ssam_name, ldap_scherr2str(code), err );
583                                 return code;
584                         }
585
586                         if ( at->at_oid == NULL ) {
587                                 fprintf( stderr, "slap_schema_load: "
588                                         "attributeType \"%s\" has no OID\n",
589                                         ad_map[i].ssam_name );
590                                 return LDAP_OTHER;
591                         }
592
593                         code = at_add( at, &err );
594                         if ( code ) {
595                                 fprintf( stderr, "slap_schema_load: "
596                                         "%s: %s: \"%s\"\n",
597                                          ad_map[i].ssam_name, scherr2str(code), err );
598                                 return code;
599                         }
600                         ldap_memfree( at );
601                 }
602         }
603
604         for( i=0; oc_map[i].ssom_name; i++ ) {
605                 if( oc_map[i].ssom_defn != NULL ) {
606                         LDAPObjectClass *oc;
607                         int             code;
608                         const char      *err;
609
610                         oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
611                                 LDAP_SCHEMA_ALLOW_ALL );
612                         if ( !oc ) {
613                                 fprintf( stderr, "slap_schema_load: "
614                                         "%s: %s before %s\n",
615                                         oc_map[i].ssom_name, ldap_scherr2str(code), err );
616                                 return code;
617                         }
618
619                         if ( oc->oc_oid == NULL ) {
620                                 fprintf( stderr, "slap_schema_load: "
621                                         "%s: objectclass has no OID\n",
622                                         oc_map[i].ssom_name );
623                                 return LDAP_OTHER;
624                         }
625
626                         code = oc_add(oc,&err);
627                         if ( code ) {
628                                 fprintf( stderr, "slap_schema_load: "
629                                         "%s: %s: \"%s\"\n",
630                                         oc_map[i].ssom_name, scherr2str(code), err);
631                                 return code;
632                         }
633
634                         ldap_memfree(oc);
635                 }
636         }
637
638         return LDAP_SUCCESS;
639 }
640
641 int
642 slap_schema_check( void )
643 {
644         int i;
645         /* we should only be called once after schema_init() was called */
646         assert( schema_init_done == 1 );
647
648         for( i=0; syn_map[i].sssm_name; i++ ) {
649                 Syntax ** synp = (Syntax **)
650                         &(((char *) &slap_schema)[syn_map[i].sssm_offset]);
651
652                 assert( *synp == NULL );
653
654                 *synp = syn_find( syn_map[i].sssm_name );
655
656                 if( *synp == NULL ) {
657                         fprintf( stderr, "slap_schema_check: "
658                                 "No syntax \"%s\" defined in schema\n",
659                                 syn_map[i].sssm_name );
660                         return LDAP_INVALID_SYNTAX;
661                 }
662         }
663
664         for( i=0; mr_map[i].ssmm_name; i++ ) {
665                 MatchingRule ** mrp = (MatchingRule **)
666                         &(((char *) &slap_schema)[mr_map[i].ssmm_offset]);
667
668                 assert( *mrp == NULL );
669
670                 *mrp = mr_find( mr_map[i].ssmm_name );
671
672                 if( *mrp == NULL ) {
673                         fprintf( stderr, "slap_schema_check: "
674                                 "No matching rule \"%s\" defined in schema\n",
675                                 mr_map[i].ssmm_name );
676                         return LDAP_INAPPROPRIATE_MATCHING;
677                 }
678         }
679
680         slap_at_undefined.sat_syntax = syn_find( SLAPD_OCTETSTRING_SYNTAX );
681         if( slap_at_undefined.sat_syntax == NULL ) {
682                 fprintf( stderr, "slap_schema_check: "
683                         "No octetString syntax \"" SLAPD_OCTETSTRING_SYNTAX "\"\n" );
684                 return LDAP_INVALID_SYNTAX;
685         }
686         slap_schema.si_at_undefined = &slap_at_undefined;
687
688         for( i=0; ad_map[i].ssam_name; i++ ) {
689                 int rc;
690                 const char *text;
691
692                 AttributeDescription ** adp = (AttributeDescription **)
693                         &(((char *) &slap_schema)[ad_map[i].ssam_offset]);
694
695                 assert( *adp == NULL );
696
697                 rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );
698                 if( rc != LDAP_SUCCESS ) {
699                         fprintf( stderr, "slap_schema_check: "
700                                 "No attribute \"%s\" defined in schema\n",
701                                 ad_map[i].ssam_name );
702                         return rc;
703                 }
704
705                 if( ad_map[i].ssam_check ) {
706                         /* install check routine */
707                         (*adp)->ad_type->sat_check = ad_map[i].ssam_check;
708                 }
709                 /* install flags */
710                 (*adp)->ad_type->sat_flags |= ad_map[i].ssam_flags;
711
712                 if( ad_map[i].ssam_match ) {
713                         /* install custom matching routine */
714                         (*adp)->ad_type->sat_equality->smr_match = ad_map[i].ssam_match;
715                 }
716         }
717
718         for( i=0; oc_map[i].ssom_name; i++ ) {
719                 ObjectClass ** ocp = (ObjectClass **)
720                         &(((char *) &slap_schema)[oc_map[i].ssom_offset]);
721
722                 assert( *ocp == NULL );
723
724                 *ocp = oc_find( oc_map[i].ssom_name );
725                 if( *ocp == NULL ) {
726                         fprintf( stderr, "slap_schema_check: "
727                                 "No objectClass \"%s\" defined in schema\n",
728                                 oc_map[i].ssom_name );
729                         return LDAP_OBJECT_CLASS_VIOLATION;
730                 }
731
732                 if( oc_map[i].ssom_check ) {
733                         /* install check routine */
734                         (*ocp)->sco_check = oc_map[i].ssom_check;
735                 }
736                 /* install flags */
737                 (*ocp)->sco_flags |= oc_map[i].ssom_flags;
738         }
739
740         ++schema_init_done;
741         return LDAP_SUCCESS;
742 }
743
744 static int rootDseObjectClass (
745         Backend *be,
746         Entry *e,
747         ObjectClass *oc,
748         const char** text,
749         char *textbuf, size_t textlen )
750 {
751         *text = textbuf;
752
753         if( e->e_nname.bv_len ) {
754                 snprintf( textbuf, textlen,
755                         "objectClass \"%s\" only allowed in the root DSE",
756                         oc->soc_oid );
757                 return LDAP_OBJECT_CLASS_VIOLATION;
758         }
759
760         /* we should not be called for the root DSE */
761         assert( 0 );
762         return LDAP_SUCCESS;
763 }
764
765 static int aliasObjectClass (
766         Backend *be,
767         Entry *e,
768         ObjectClass *oc,
769         const char** text,
770         char *textbuf, size_t textlen )
771 {
772         *text = textbuf;
773
774         if( !SLAP_ALIASES(be) ) {
775                 snprintf( textbuf, textlen,
776                         "objectClass \"%s\" not supported in context",
777                         oc->soc_oid );
778                 return LDAP_OBJECT_CLASS_VIOLATION;
779         }
780
781         return LDAP_SUCCESS;
782 }
783
784 static int referralObjectClass (
785         Backend *be,
786         Entry *e,
787         ObjectClass *oc,
788         const char** text,
789         char *textbuf, size_t textlen )
790 {
791         *text = textbuf;
792
793         if( !SLAP_REFERRALS(be) ) {
794                 snprintf( textbuf, textlen,
795                         "objectClass \"%s\" not supported in context",
796                         oc->soc_oid );
797                 return LDAP_OBJECT_CLASS_VIOLATION;
798         }
799
800         return LDAP_SUCCESS;
801 }
802
803 static int subentryObjectClass (
804         Backend *be,
805         Entry *e,
806         ObjectClass *oc,
807         const char** text,
808         char *textbuf, size_t textlen )
809 {
810         *text = textbuf;
811
812         if( !SLAP_SUBENTRIES(be) ) {
813                 snprintf( textbuf, textlen,
814                         "objectClass \"%s\" not supported in context",
815                         oc->soc_oid );
816                 return LDAP_OBJECT_CLASS_VIOLATION;
817         }
818
819         if( oc != slap_schema.si_oc_subentry && !is_entry_subentry( e ) ) {
820                 snprintf( textbuf, textlen,
821                         "objectClass \"%s\" only allowed in subentries",
822                         oc->soc_oid );
823                 return LDAP_OBJECT_CLASS_VIOLATION;
824         }
825
826         return LDAP_SUCCESS;
827 }
828
829 static int dynamicObjectClass (
830         Backend *be,
831         Entry *e,
832         ObjectClass *oc,
833         const char** text,
834         char *textbuf, size_t textlen )
835 {
836         *text = textbuf;
837
838         if( !SLAP_DYNAMIC(be) ) {
839                 snprintf( textbuf, textlen,
840                         "objectClass \"%s\" not supported in context",
841                         oc->soc_oid );
842                 return LDAP_OBJECT_CLASS_VIOLATION;
843         }
844
845         return LDAP_SUCCESS;
846 }
847
848 static int rootDseAttribute (
849         Backend *be,
850         Entry *e,
851         Attribute *attr,
852         const char** text,
853         char *textbuf, size_t textlen )
854 {
855         *text = textbuf;
856
857         if( e->e_nname.bv_len ) {
858                 snprintf( textbuf, textlen,
859                         "attribute \"%s\" only allowed in the root DSE",
860                         attr->a_desc->ad_cname.bv_val );
861                 return LDAP_OBJECT_CLASS_VIOLATION;
862         }
863
864         /* we should not be called for the root DSE */
865         assert( 0 );
866         return LDAP_SUCCESS;
867 }
868
869 static int aliasAttribute (
870         Backend *be,
871         Entry *e,
872         Attribute *attr,
873         const char** text,
874         char *textbuf, size_t textlen )
875 {
876         *text = textbuf;
877
878         if( !SLAP_ALIASES(be) ) {
879                 snprintf( textbuf, textlen,
880                         "attribute \"%s\" not supported in context",
881                         attr->a_desc->ad_cname.bv_val );
882                 return LDAP_OBJECT_CLASS_VIOLATION;
883         }
884
885         if( !is_entry_alias( e ) ) {
886                 snprintf( textbuf, textlen,
887                         "attribute \"%s\" only allowed in the alias",
888                         attr->a_desc->ad_cname.bv_val );
889                 return LDAP_OBJECT_CLASS_VIOLATION;
890         }
891
892         return LDAP_SUCCESS;
893 }
894
895 static int referralAttribute (
896         Backend *be,
897         Entry *e,
898         Attribute *attr,
899         const char** text,
900         char *textbuf, size_t textlen )
901 {
902         *text = textbuf;
903
904         if( !SLAP_REFERRALS(be) ) {
905                 snprintf( textbuf, textlen,
906                         "attribute \"%s\" not supported in context",
907                         attr->a_desc->ad_cname.bv_val );
908                 return LDAP_OBJECT_CLASS_VIOLATION;
909         }
910
911         if( !is_entry_referral( e ) ) {
912                 snprintf( textbuf, textlen,
913                         "attribute \"%s\" only allowed in the referral",
914                         attr->a_desc->ad_cname.bv_val );
915                 return LDAP_OBJECT_CLASS_VIOLATION;
916         }
917
918         return LDAP_SUCCESS;
919 }
920
921 static int subentryAttribute (
922         Backend *be,
923         Entry *e,
924         Attribute *attr,
925         const char** text,
926         char *textbuf, size_t textlen )
927 {
928         *text = textbuf;
929
930         if( !SLAP_SUBENTRIES(be) ) {
931                 snprintf( textbuf, textlen,
932                         "attribute \"%s\" not supported in context",
933                         attr->a_desc->ad_cname.bv_val );
934                 return LDAP_OBJECT_CLASS_VIOLATION;
935         }
936
937         if( !is_entry_subentry( e ) ) {
938                 snprintf( textbuf, textlen,
939                         "attribute \"%s\" only allowed in the subentry",
940                         attr->a_desc->ad_cname.bv_val );
941                 return LDAP_OBJECT_CLASS_VIOLATION;
942         }
943
944         return LDAP_SUCCESS;
945 }
946
947 static int dynamicAttribute (
948         Backend *be,
949         Entry *e,
950         Attribute *attr,
951         const char** text,
952         char *textbuf, size_t textlen )
953 {
954         *text = textbuf;
955
956         if( !SLAP_DYNAMIC(be) ) {
957                 snprintf( textbuf, textlen,
958                         "attribute \"%s\" not supported in context",
959                         attr->a_desc->ad_cname.bv_val );
960                 return LDAP_OBJECT_CLASS_VIOLATION;
961         }
962
963         if( !is_entry_dynamicObject( e ) ) {
964                 snprintf( textbuf, textlen,
965                         "attribute \"%s\" only allowed in dynamic object",
966                         attr->a_desc->ad_cname.bv_val );
967                 return LDAP_OBJECT_CLASS_VIOLATION;
968         }
969
970         return LDAP_SUCCESS;
971 }