]> git.sur5r.net Git - openldap/blob - servers/slapd/oc.c
a8997bc7792c064062da1c6d3e7d989a9e926272
[openldap] / servers / slapd / oc.c
1 /* oc.c - object class routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 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
19 int is_entry_objectclass(
20         Entry*  e,
21         const char*     oc)
22 {
23         Attribute *attr;
24         struct berval bv;
25 #ifdef SLAPD_SCHEMA_NOT_COMPAT
26         static AttributeDescription *objectClass = NULL;
27 #else
28         static const char *objectClass = "objectclass";
29 #endif
30
31         if( e == NULL || oc == NULL || *oc == '\0' )
32                 return 0;
33
34         /*
35          * find objectClass attribute
36          */
37         attr = attr_find(e->e_attrs, objectClass);
38
39         if( attr == NULL ) {
40                 /* no objectClass attribute */
41                 return 0;
42         }
43
44         bv.bv_val = (char *) oc;
45         bv.bv_len = strlen( bv.bv_val );
46
47 #ifdef SLAPD_SCHEMA_NOT_COMPAT
48         /* not yet implemented */
49 #else
50         if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
51                 /* entry is not of this objectclass */
52                 return 0;
53         }
54 #endif
55
56         return 1;
57 }
58
59
60 #ifndef SLAPD_SCHEMA_NOT_COMPAT
61         /* these shouldn't be hardcoded */
62
63 static char *oc_op_usermod_attrs[] = {
64         /*
65          * these are operational attributes which are
66          * not defined as NO-USER_MODIFICATION and
67          * which slapd supports modification of.
68          *
69          * Currently none.
70          * Likely candidate, "aci"
71          */
72         NULL
73 };
74
75 static char *oc_op_attrs[] = {
76         /*
77          * these are operational attributes 
78          * most could be user modifiable
79          */
80         "objectClasses",
81         "attributeTypes",
82         "matchingRules",
83         "matchingRuleUse",
84         "dITStructureRules",
85         "dITContentRules",
86         "nameForms",
87         "ldapSyntaxes",
88         "namingContexts",
89         "supportedExtension",
90         "supportedControl",
91         "supportedSASLMechanisms",
92         "supportedLDAPversion",
93         "supportedACIMechanisms",
94         "subschemaSubentry",            /* NO USER MOD */
95         NULL
96
97 };
98
99 /* this list should be extensible  */
100 static char *oc_op_no_usermod_attrs[] = {
101         /*
102          * Operational and 'no user modification' attributes
103          * which are STORED in the directory server.
104          */
105
106         /* RFC2252, 3.2.1 */
107         "creatorsName",
108         "createTimestamp",
109         "modifiersName",
110         "modifyTimestamp",
111
112         NULL
113 };
114 #endif
115
116
117 /*
118  * check to see if attribute is 'operational' or not.
119  */
120 int
121 oc_check_op_attr( const char *type )
122 {
123 #ifndef SLAPD_SCHEMA_NOT_COMPAT
124         return charray_inlist( oc_op_attrs, type )
125                 || charray_inlist( oc_op_usermod_attrs, type )
126                 || charray_inlist( oc_op_no_usermod_attrs, type );
127 #else
128         AttributeType *at = at_find( type );
129
130         if( at == NULL ) return 0;
131
132         return at->sat_usage != LDAP_SCHEMA_USER_APPLICATIONS;
133 #endif
134 }
135
136 /*
137  * check to see if attribute can be user modified or not.
138  */
139 int
140 oc_check_op_usermod_attr( const char *type )
141 {
142 #ifndef SLAPD_SCHEMA_NOT_COMPAT
143         return charray_inlist( oc_op_usermod_attrs, type );
144 #else
145         /* not (yet) in schema */
146         return 0;
147 #endif
148 }
149
150 /*
151  * check to see if attribute is 'no user modification' or not.
152  */
153 int
154 oc_check_op_no_usermod_attr( const char *type )
155 {
156 #ifndef SLAPD_SCHEMA_NOT_COMPAT
157         return charray_inlist( oc_op_no_usermod_attrs, type );
158 #else
159         AttributeType *at = at_find( type );
160
161         if( at == NULL ) return 0;
162
163         return at->sat_no_user_mod;
164 #endif
165 }
166
167
168 struct oindexrec {
169         char            *oir_name;
170         ObjectClass     *oir_oc;
171 };
172
173 static Avlnode  *oc_index = NULL;
174 static ObjectClass *oc_list = NULL;
175
176 static int
177 oc_index_cmp(
178     struct oindexrec    *oir1,
179     struct oindexrec    *oir2
180 )
181 {
182         return (strcasecmp( oir1->oir_name, oir2->oir_name ));
183 }
184
185 static int
186 oc_index_name_cmp(
187     char                *name,
188     struct oindexrec    *oir
189 )
190 {
191         return (strcasecmp( name, oir->oir_name ));
192 }
193
194 ObjectClass *
195 oc_find( const char *ocname )
196 {
197         struct oindexrec        *oir = NULL;
198
199         if ( (oir = (struct oindexrec *) avl_find( oc_index, ocname,
200             (AVL_CMP) oc_index_name_cmp )) != NULL ) {
201                 return( oir->oir_oc );
202         }
203         return( NULL );
204 }
205
206 static int
207 oc_create_required(
208     ObjectClass         *soc,
209     char                **attrs,
210     const char          **err
211 )
212 {
213         char            **attrs1;
214         AttributeType   *sat;
215         AttributeType   **satp;
216         int             i;
217
218         if ( attrs ) {
219                 attrs1 = attrs;
220                 while ( *attrs1 ) {
221                         sat = at_find(*attrs1);
222                         if ( !sat ) {
223                                 *err = *attrs1;
224                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
225                         }
226                         if ( at_find_in_list(sat, soc->soc_required) < 0) {
227                                 if ( at_append_to_list(sat, &soc->soc_required) ) {
228                                         *err = *attrs1;
229                                         return SLAP_SCHERR_OUTOFMEM;
230                                 }
231                         }
232                         attrs1++;
233                 }
234                 /* Now delete duplicates from the allowed list */
235                 for ( satp = soc->soc_required; *satp; satp++ ) {
236                         i = at_find_in_list(*satp,soc->soc_allowed);
237                         if ( i >= 0 ) {
238                                 at_delete_from_list(i, &soc->soc_allowed);
239                         }
240                 }
241         }
242         return 0;
243 }
244
245 static int
246 oc_create_allowed(
247     ObjectClass         *soc,
248     char                **attrs,
249     const char          **err
250 )
251 {
252         char            **attrs1;
253         AttributeType   *sat;
254
255         if ( attrs ) {
256                 attrs1 = attrs;
257                 while ( *attrs1 ) {
258                         sat = at_find(*attrs1);
259                         if ( !sat ) {
260                                 *err = *attrs1;
261                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
262                         }
263                         if ( at_find_in_list(sat, soc->soc_required) < 0 &&
264                              at_find_in_list(sat, soc->soc_allowed) < 0 ) {
265                                 if ( at_append_to_list(sat, &soc->soc_allowed) ) {
266                                         *err = *attrs1;
267                                         return SLAP_SCHERR_OUTOFMEM;
268                                 }
269                         }
270                         attrs1++;
271                 }
272         }
273         return 0;
274 }
275
276 static int
277 oc_add_sups(
278     ObjectClass         *soc,
279     char                **sups,
280     const char          **err
281 )
282 {
283         int             code;
284         ObjectClass     *soc1;
285         int             nsups;
286         char            **sups1;
287         int             add_sups = 0;
288
289         if ( sups ) {
290                 if ( !soc->soc_sups ) {
291                         /* We are at the first recursive level */
292                         add_sups = 1;
293                         nsups = 0;
294                         sups1 = sups;
295                         while ( *sups1 ) {
296                                 nsups++;
297                                 sups1++;
298                         }
299                         nsups++;
300                         soc->soc_sups = (ObjectClass **)ch_calloc(nsups,
301                                           sizeof(ObjectClass *));
302                 }
303                 nsups = 0;
304                 sups1 = sups;
305                 while ( *sups1 ) {
306                         soc1 = oc_find(*sups1);
307                         if ( !soc1 ) {
308                                 *err = *sups1;
309                                 return SLAP_SCHERR_CLASS_NOT_FOUND;
310                         }
311
312                         if ( add_sups )
313                                 soc->soc_sups[nsups] = soc1;
314
315                         code = oc_add_sups(soc,soc1->soc_sup_oids, err);
316                         if ( code )
317                                 return code;
318
319                         code = oc_create_required(soc,soc1->soc_at_oids_must,err);
320                         if ( code )
321                                 return code;
322                         code = oc_create_allowed(soc,soc1->soc_at_oids_may,err);
323                         if ( code )
324                                 return code;
325
326                         nsups++;
327                         sups1++;
328                 }
329         }
330         return 0;
331 }
332
333 static int
334 oc_insert(
335     ObjectClass         *soc,
336     const char          **err
337 )
338 {
339         ObjectClass     **ocp;
340         struct oindexrec        *oir;
341         char                    **names;
342
343         ocp = &oc_list;
344         while ( *ocp != NULL ) {
345                 ocp = &(*ocp)->soc_next;
346         }
347         *ocp = soc;
348
349         if ( soc->soc_oid ) {
350                 oir = (struct oindexrec *)
351                         ch_calloc( 1, sizeof(struct oindexrec) );
352                 oir->oir_name = soc->soc_oid;
353                 oir->oir_oc = soc;
354                 if ( avl_insert( &oc_index, (caddr_t) oir,
355                                  (AVL_CMP) oc_index_cmp,
356                                  (AVL_DUP) avl_dup_error ) ) {
357                         *err = soc->soc_oid;
358                         ldap_memfree(oir);
359                         return SLAP_SCHERR_DUP_CLASS;
360                 }
361                 /* FIX: temporal consistency check */
362                 oc_find(oir->oir_name);
363         }
364         if ( (names = soc->soc_names) ) {
365                 while ( *names ) {
366                         oir = (struct oindexrec *)
367                                 ch_calloc( 1, sizeof(struct oindexrec) );
368                         oir->oir_name = ch_strdup(*names);
369                         oir->oir_oc = soc;
370                         if ( avl_insert( &oc_index, (caddr_t) oir,
371                                          (AVL_CMP) oc_index_cmp,
372                                          (AVL_DUP) avl_dup_error ) ) {
373                                 *err = *names;
374                                 ldap_memfree(oir);
375                                 return SLAP_SCHERR_DUP_CLASS;
376                         }
377                         /* FIX: temporal consistency check */
378                         oc_find(oir->oir_name);
379                         names++;
380                 }
381         }
382         return 0;
383 }
384
385 int
386 oc_add(
387     LDAP_OBJECT_CLASS   *oc,
388     const char          **err
389 )
390 {
391         ObjectClass     *soc;
392         int             code;
393
394         soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
395         memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
396         if ( (code = oc_add_sups(soc,soc->soc_sup_oids,err)) != 0 )
397                 return code;
398         if ( (code = oc_create_required(soc,soc->soc_at_oids_must,err)) != 0 )
399                 return code;
400         if ( (code = oc_create_allowed(soc,soc->soc_at_oids_may,err)) != 0 )
401                 return code;
402         code = oc_insert(soc,err);
403         return code;
404 }
405
406 #ifdef LDAP_DEBUG
407
408 static void
409 oc_print( ObjectClass *oc )
410 {
411         int     i;
412         const char *mid;
413
414         printf( "objectclass %s\n", ldap_objectclass2name( &oc->soc_oclass ) );
415         if ( oc->soc_required != NULL ) {
416                 mid = "\trequires ";
417                 for ( i = 0; oc->soc_required[i] != NULL; i++, mid = "," )
418                         printf( "%s%s", mid,
419                                 ldap_attributetype2name( &oc->soc_required[i]->sat_atype ) );
420                 printf( "\n" );
421         }
422         if ( oc->soc_allowed != NULL ) {
423                 mid = "\tallows ";
424                 for ( i = 0; oc->soc_allowed[i] != NULL; i++, mid = "," )
425                         printf( "%s%s", mid,
426                                 ldap_attributetype2name( &oc->soc_allowed[i]->sat_atype ) );
427                 printf( "\n" );
428         }
429 }
430
431 #endif
432
433
434 #if defined( SLAPD_SCHEMA_DN )
435
436 int
437 oc_schema_info( Entry *e )
438 {
439         struct berval   val;
440         struct berval   *vals[2];
441         ObjectClass     *oc;
442
443         vals[0] = &val;
444         vals[1] = NULL;
445
446         for ( oc = oc_list; oc; oc = oc->soc_next ) {
447                 val.bv_val = ldap_objectclass2str( &oc->soc_oclass );
448                 if ( val.bv_val ) {
449                         val.bv_len = strlen( val.bv_val );
450                         Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n",
451                                (long) val.bv_len, val.bv_val, 0 );
452                         attr_merge( e, "objectClasses", vals );
453                         ldap_memfree( val.bv_val );
454                 } else {
455                         return -1;
456                 }
457         }
458         return 0;
459 }
460
461 #endif