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