]> git.sur5r.net Git - openldap/blob - servers/slapd/oc.c
6fa5dcfa0a3ced7f9bd188fb6c100be2b8d5b95a
[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         assert( oir1->oir_name );
209         assert( oir1->oir_oc );
210         assert( oir2->oir_name );
211         assert( oir2->oir_oc );
212
213         return (strcasecmp( oir1->oir_name, oir2->oir_name ));
214 }
215
216 static int
217 oc_index_name_cmp(
218     char                *name,
219     struct oindexrec    *oir
220 )
221 {
222         assert( oir->oir_name );
223         assert( oir->oir_oc );
224
225         return (strcasecmp( name, oir->oir_name ));
226 }
227
228 ObjectClass *
229 oc_find( const char *ocname )
230 {
231         struct oindexrec        *oir;
232
233         oir = (struct oindexrec *) avl_find( oc_index, ocname,
234             (AVL_CMP) oc_index_name_cmp );
235
236         if ( oir != NULL ) {
237                 assert( oir->oir_name );
238                 assert( oir->oir_oc );
239
240                 return( oir->oir_oc );
241         }
242
243         return( NULL );
244 }
245
246 static int
247 oc_create_required(
248     ObjectClass         *soc,
249     char                **attrs,
250     const char          **err
251 )
252 {
253         char            **attrs1;
254         AttributeType   *sat;
255         AttributeType   **satp;
256         int             i;
257
258         if ( attrs ) {
259                 attrs1 = attrs;
260                 while ( *attrs1 ) {
261                         sat = at_find(*attrs1);
262                         if ( !sat ) {
263                                 *err = *attrs1;
264                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
265                         }
266                         if ( at_find_in_list(sat, soc->soc_required) < 0) {
267                                 if ( at_append_to_list(sat, &soc->soc_required) ) {
268                                         *err = *attrs1;
269                                         return SLAP_SCHERR_OUTOFMEM;
270                                 }
271                         }
272                         attrs1++;
273                 }
274                 /* Now delete duplicates from the allowed list */
275                 for ( satp = soc->soc_required; *satp; satp++ ) {
276                         i = at_find_in_list(*satp,soc->soc_allowed);
277                         if ( i >= 0 ) {
278                                 at_delete_from_list(i, &soc->soc_allowed);
279                         }
280                 }
281         }
282         return 0;
283 }
284
285 static int
286 oc_create_allowed(
287     ObjectClass         *soc,
288     char                **attrs,
289     const char          **err
290 )
291 {
292         char            **attrs1;
293         AttributeType   *sat;
294
295         if ( attrs ) {
296                 attrs1 = attrs;
297                 while ( *attrs1 ) {
298                         sat = at_find(*attrs1);
299                         if ( !sat ) {
300                                 *err = *attrs1;
301                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
302                         }
303                         if ( at_find_in_list(sat, soc->soc_required) < 0 &&
304                              at_find_in_list(sat, soc->soc_allowed) < 0 ) {
305                                 if ( at_append_to_list(sat, &soc->soc_allowed) ) {
306                                         *err = *attrs1;
307                                         return SLAP_SCHERR_OUTOFMEM;
308                                 }
309                         }
310                         attrs1++;
311                 }
312         }
313         return 0;
314 }
315
316 static int
317 oc_add_sups(
318     ObjectClass         *soc,
319     char                **sups,
320     const char          **err
321 )
322 {
323         int             code;
324         ObjectClass     *soc1;
325         int             nsups;
326         char            **sups1;
327         int             add_sups = 0;
328
329         if ( sups ) {
330                 if ( !soc->soc_sups ) {
331                         /* We are at the first recursive level */
332                         add_sups = 1;
333                         nsups = 0;
334                         sups1 = sups;
335                         while ( *sups1 ) {
336                                 nsups++;
337                                 sups1++;
338                         }
339                         nsups++;
340                         soc->soc_sups = (ObjectClass **)ch_calloc(nsups,
341                                           sizeof(ObjectClass *));
342                 }
343                 nsups = 0;
344                 sups1 = sups;
345                 while ( *sups1 ) {
346                         soc1 = oc_find(*sups1);
347                         if ( !soc1 ) {
348                                 *err = *sups1;
349                                 return SLAP_SCHERR_CLASS_NOT_FOUND;
350                         }
351
352                         if ( add_sups )
353                                 soc->soc_sups[nsups] = soc1;
354
355                         code = oc_add_sups(soc,soc1->soc_sup_oids, err);
356                         if ( code )
357                                 return code;
358
359                         code = oc_create_required(soc,soc1->soc_at_oids_must,err);
360                         if ( code )
361                                 return code;
362                         code = oc_create_allowed(soc,soc1->soc_at_oids_may,err);
363                         if ( code )
364                                 return code;
365
366                         nsups++;
367                         sups1++;
368                 }
369         }
370         return 0;
371 }
372
373 static int
374 oc_insert(
375     ObjectClass         *soc,
376     const char          **err
377 )
378 {
379         ObjectClass     **ocp;
380         struct oindexrec        *oir;
381         char                    **names;
382
383         ocp = &oc_list;
384         while ( *ocp != NULL ) {
385                 ocp = &(*ocp)->soc_next;
386         }
387         *ocp = soc;
388
389         if ( soc->soc_oid ) {
390                 oir = (struct oindexrec *)
391                         ch_calloc( 1, sizeof(struct oindexrec) );
392                 oir->oir_name = soc->soc_oid;
393                 oir->oir_oc = soc;
394
395                 assert( oir->oir_name );
396                 assert( oir->oir_oc );
397
398                 if ( avl_insert( &oc_index, (caddr_t) oir,
399                                  (AVL_CMP) oc_index_cmp,
400                                  (AVL_DUP) avl_dup_error ) )
401                 {
402                         *err = soc->soc_oid;
403                         ldap_memfree(oir->oir_name);
404                         ldap_memfree(oir);
405                         return SLAP_SCHERR_DUP_CLASS;
406                 }
407
408                 /* FIX: temporal consistency check */
409                 assert( oc_find(oir->oir_name) != NULL );
410         }
411
412         if ( (names = soc->soc_names) ) {
413                 while ( *names ) {
414                         oir = (struct oindexrec *)
415                                 ch_calloc( 1, sizeof(struct oindexrec) );
416                         oir->oir_name = ch_strdup(*names);
417                         oir->oir_oc = soc;
418
419                         assert( oir->oir_name );
420                         assert( oir->oir_oc );
421
422                         if ( avl_insert( &oc_index, (caddr_t) oir,
423                                          (AVL_CMP) oc_index_cmp,
424                                          (AVL_DUP) avl_dup_error ) )
425                         {
426                                 *err = *names;
427                                 ldap_memfree(oir->oir_name);
428                                 ldap_memfree(oir);
429                                 return SLAP_SCHERR_DUP_CLASS;
430                         }
431
432                         /* FIX: temporal consistency check */
433                         assert( oc_find(oir->oir_name) != NULL );
434
435                         names++;
436                 }
437         }
438
439         return 0;
440 }
441
442 int
443 oc_add(
444     LDAP_OBJECT_CLASS   *oc,
445     const char          **err
446 )
447 {
448         ObjectClass     *soc;
449         int             code;
450
451         soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
452         memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
453         if ( (code = oc_add_sups(soc,soc->soc_sup_oids,err)) != 0 )
454                 return code;
455         if ( (code = oc_create_required(soc,soc->soc_at_oids_must,err)) != 0 )
456                 return code;
457         if ( (code = oc_create_allowed(soc,soc->soc_at_oids_may,err)) != 0 )
458                 return code;
459         code = oc_insert(soc,err);
460         return code;
461 }
462
463 #ifdef LDAP_DEBUG
464
465 static void
466 oc_print( ObjectClass *oc )
467 {
468         int     i;
469         const char *mid;
470
471         printf( "objectclass %s\n", ldap_objectclass2name( &oc->soc_oclass ) );
472         if ( oc->soc_required != NULL ) {
473                 mid = "\trequires ";
474                 for ( i = 0; oc->soc_required[i] != NULL; i++, mid = "," )
475                         printf( "%s%s", mid,
476                                 ldap_attributetype2name( &oc->soc_required[i]->sat_atype ) );
477                 printf( "\n" );
478         }
479         if ( oc->soc_allowed != NULL ) {
480                 mid = "\tallows ";
481                 for ( i = 0; oc->soc_allowed[i] != NULL; i++, mid = "," )
482                         printf( "%s%s", mid,
483                                 ldap_attributetype2name( &oc->soc_allowed[i]->sat_atype ) );
484                 printf( "\n" );
485         }
486 }
487
488 #endif
489
490
491 #if defined( SLAPD_SCHEMA_DN )
492
493 int
494 oc_schema_info( Entry *e )
495 {
496         struct berval   val;
497         struct berval   *vals[2];
498         ObjectClass     *oc;
499
500 #ifdef SLAPD_SCHEMA_NOT_COMPAT
501         AttributeDescription *ad_objectClasses = slap_schema.si_ad_objectClasses;
502 #else
503         char *ad_objectClasses = "objectClasses";
504 #endif
505
506         vals[0] = &val;
507         vals[1] = NULL;
508
509         for ( oc = oc_list; oc; oc = oc->soc_next ) {
510                 val.bv_val = ldap_objectclass2str( &oc->soc_oclass );
511                 if ( val.bv_val == NULL ) {
512                         return -1;
513                 }
514                 val.bv_len = strlen( val.bv_val );
515 #if 0
516                 Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n",
517                (long) val.bv_len, val.bv_val, 0 );
518 #endif
519                 attr_merge( e, ad_objectClasses, vals );
520                 ldap_memfree( val.bv_val );
521         }
522         return 0;
523 }
524
525 #endif