]> git.sur5r.net Git - openldap/blob - servers/slapd/oc.c
Remove casts of AVL function pointers.
[openldap] / servers / slapd / oc.c
1 /* oc.c - object class routines */
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
19 int is_object_subclass(
20         ObjectClass *sup,
21         ObjectClass *sub )
22 {
23         int i;
24
25         if( sub == NULL || sup == NULL ) return 0;
26
27 #if 1
28 #ifdef NEW_LOGGING
29         LDAP_LOG ( OPERATION, ARGS, 
30                 "is_object_subclass(%s,%s) %d\n",
31                 sup->soc_oid, sub->soc_oid, sup == sub );
32 #else
33         Debug( LDAP_DEBUG_TRACE, "is_object_subclass(%s,%s) %d\n",
34                 sup->soc_oid, sub->soc_oid, sup == sub );
35 #endif
36 #endif
37
38         if( sup == sub ) {
39                 return 1;
40         }
41
42         if( sub->soc_sups == NULL ) {
43                 return 0;
44         }
45
46         for( i=0; sub->soc_sups[i] != NULL; i++ ) {
47                 if( is_object_subclass( sup, sub->soc_sups[i] ) ) {
48                         return 1;
49                 }
50         }
51
52         return 0;
53 }
54
55 int is_entry_objectclass(
56         Entry*  e,
57         ObjectClass *oc,
58         int set_flags )
59 {
60         Attribute *attr;
61         struct berval *bv;
62         AttributeDescription *objectClass = slap_schema.si_ad_objectClass;
63         assert(!( e == NULL || oc == NULL ));
64
65         if( e == NULL || oc == NULL ) {
66                 return 0;
67         }
68
69         if( set_flags && ( e->e_ocflags & SLAP_OC__END )) {
70                 return (e->e_ocflags & oc->soc_flags) == oc->soc_flags;
71         }
72
73         /*
74          * find objectClass attribute
75          */
76         attr = attr_find(e->e_attrs, objectClass);
77
78         if( attr == NULL ) {
79                 /* no objectClass attribute */
80 #ifdef NEW_LOGGING
81                 LDAP_LOG( OPERATION, ERR, 
82                         "is_entry_objectclass: dn(%s), oid (%s), no objectClass "
83                         "attribute.\n", e->e_dn == NULL ? "" : e->e_dn,
84                         oc->soc_oclass.oc_oid, 0 );
85 #else
86                 Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") "
87                         "no objectClass attribute\n",
88                         e->e_dn == NULL ? "" : e->e_dn,
89                         oc->soc_oclass.oc_oid, 0 );
90 #endif
91
92                 return 0;
93         }
94
95         for( bv=attr->a_vals; bv->bv_val; bv++ ) {
96                 ObjectClass *objectClass = oc_bvfind( bv );
97
98                 if ( objectClass == oc && !set_flags ) {
99                         return 1;
100                 }
101                 
102                 if ( objectClass != NULL ) {
103                         e->e_ocflags |= objectClass->soc_flags;
104                 }
105         }
106         e->e_ocflags |= SLAP_OC__END;   /* We've finished this */
107
108         return (e->e_ocflags & oc->soc_flags) == oc->soc_flags;
109 }
110
111
112 struct oindexrec {
113         struct berval   oir_name;
114         ObjectClass     *oir_oc;
115 };
116
117 static Avlnode  *oc_index = NULL;
118 static ObjectClass *oc_list = NULL;
119
120 static int
121 oc_index_cmp(
122         const void *v_oir1,
123         const void *v_oir2 )
124 {
125         const struct oindexrec *oir1 = v_oir1, *oir2 = v_oir2;
126         int i = oir1->oir_name.bv_len - oir2->oir_name.bv_len;
127         if (i)
128                 return i;
129         return strcasecmp( oir1->oir_name.bv_val, oir2->oir_name.bv_val );
130 }
131
132 static int
133 oc_index_name_cmp(
134         const void *v_name,
135         const void *v_oir )
136 {
137         const struct berval    *name = v_name;
138         const struct oindexrec *oir  = v_oir;
139         int i = name->bv_len - oir->oir_name.bv_len;
140         if (i)
141                 return i;
142         return strncasecmp( name->bv_val, oir->oir_name.bv_val, name->bv_len );
143 }
144
145 ObjectClass *
146 oc_find( const char *ocname )
147 {
148         struct berval bv;
149
150         bv.bv_val = (char *)ocname;
151         bv.bv_len = strlen( ocname );
152
153         return( oc_bvfind( &bv ) );
154 }
155
156 ObjectClass *
157 oc_bvfind( struct berval *ocname )
158 {
159         struct oindexrec        *oir;
160
161         oir = avl_find( oc_index, ocname, oc_index_name_cmp );
162
163         if ( oir != NULL ) {
164                 return( oir->oir_oc );
165         }
166
167         return( NULL );
168 }
169
170 static int
171 oc_create_required(
172     ObjectClass         *soc,
173     char                **attrs,
174         int                     *op,
175     const char          **err )
176 {
177         char            **attrs1;
178         AttributeType   *sat;
179         AttributeType   **satp;
180         int             i;
181
182         if ( attrs ) {
183                 attrs1 = attrs;
184                 while ( *attrs1 ) {
185                         sat = at_find(*attrs1);
186                         if ( !sat ) {
187                                 *err = *attrs1;
188                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
189                         }
190
191                         if( is_at_operational( sat )) (*op)++;
192
193                         if ( at_find_in_list(sat, soc->soc_required) < 0) {
194                                 if ( at_append_to_list(sat, &soc->soc_required) ) {
195                                         *err = *attrs1;
196                                         return SLAP_SCHERR_OUTOFMEM;
197                                 }
198                         }
199                         attrs1++;
200                 }
201                 /* Now delete duplicates from the allowed list */
202                 for ( satp = soc->soc_required; *satp; satp++ ) {
203                         i = at_find_in_list(*satp,soc->soc_allowed);
204                         if ( i >= 0 ) {
205                                 at_delete_from_list(i, &soc->soc_allowed);
206                         }
207                 }
208         }
209         return 0;
210 }
211
212 static int
213 oc_create_allowed(
214     ObjectClass         *soc,
215     char                **attrs,
216         int                     *op,
217     const char          **err )
218 {
219         char            **attrs1;
220         AttributeType   *sat;
221
222         if ( attrs ) {
223                 attrs1 = attrs;
224                 while ( *attrs1 ) {
225                         sat = at_find(*attrs1);
226                         if ( !sat ) {
227                                 *err = *attrs1;
228                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
229                         }
230
231                         if( is_at_operational( sat )) (*op)++;
232
233                         if ( at_find_in_list(sat, soc->soc_required) < 0 &&
234                              at_find_in_list(sat, soc->soc_allowed) < 0 ) {
235                                 if ( at_append_to_list(sat, &soc->soc_allowed) ) {
236                                         *err = *attrs1;
237                                         return SLAP_SCHERR_OUTOFMEM;
238                                 }
239                         }
240                         attrs1++;
241                 }
242         }
243         return 0;
244 }
245
246 static int
247 oc_add_sups(
248     ObjectClass         *soc,
249     char                        **sups,
250         int                     *op,
251     const char          **err )
252 {
253         int             code;
254         ObjectClass     *soc1;
255         int             nsups;
256         char    **sups1;
257         int             add_sups = 0;
258
259         if ( sups ) {
260                 if ( !soc->soc_sups ) {
261                         /* We are at the first recursive level */
262                         add_sups = 1;
263                         nsups = 1;
264                         sups1 = sups;
265                         while ( *sups1 ) {
266                                 nsups++;
267                                 sups1++;
268                         }
269                         soc->soc_sups = (ObjectClass **)ch_calloc(nsups,
270                                           sizeof(ObjectClass *));
271                 }
272
273                 nsups = 0;
274                 sups1 = sups;
275                 while ( *sups1 ) {
276                         soc1 = oc_find(*sups1);
277                         if ( !soc1 ) {
278                                 *err = *sups1;
279                                 return SLAP_SCHERR_CLASS_NOT_FOUND;
280                         }
281
282                         /* check object class usage
283                          * abstract classes can only sup abstract classes 
284                          * structural classes can not sup auxiliary classes
285                          * auxiliary classes can not sup structural classes
286                          */
287                         if( soc->soc_kind != soc1->soc_kind
288                                 && soc1->soc_kind != LDAP_SCHEMA_ABSTRACT )
289                         {
290                                 *err = *sups1;
291                                 return SLAP_SCHERR_CLASS_BAD_SUP;
292                         }
293
294                         if( soc1->soc_obsolete && !soc->soc_obsolete ) {
295                                 *err = *sups1;
296                                 return SLAP_SCHERR_CLASS_BAD_SUP;
297                         }
298
299                         if( soc->soc_flags & SLAP_OC_OPERATIONAL ) (*op)++;
300
301                         if ( add_sups ) {
302                                 soc->soc_sups[nsups] = soc1;
303                         }
304
305                         code = oc_add_sups( soc, soc1->soc_sup_oids, op, err );
306                         if ( code ) return code;
307
308                         code = oc_create_required( soc, soc1->soc_at_oids_must, op, err );
309                         if ( code ) return code;
310
311                         code = oc_create_allowed( soc, soc1->soc_at_oids_may, op, err );
312                         if ( code ) return code;
313
314                         nsups++;
315                         sups1++;
316                 }
317         }
318
319         return 0;
320 }
321
322 void
323 oc_destroy( void )
324 {
325         ObjectClass *o, *n;
326
327         avl_free(oc_index, ldap_memfree);
328         for (o=oc_list; o; o=n)
329         {
330                 n = o->soc_next;
331                 if (o->soc_sups) ldap_memfree(o->soc_sups);
332                 if (o->soc_required) ldap_memfree(o->soc_required);
333                 if (o->soc_allowed) ldap_memfree(o->soc_allowed);
334                 ldap_objectclass_free((LDAPObjectClass *)o);
335         }
336 }
337
338 static int
339 oc_insert(
340     ObjectClass         *soc,
341     const char          **err
342 )
343 {
344         ObjectClass     **ocp;
345         struct oindexrec        *oir;
346         char                    **names;
347
348         ocp = &oc_list;
349         while ( *ocp != NULL ) {
350                 ocp = &(*ocp)->soc_next;
351         }
352         *ocp = soc;
353
354         if ( soc->soc_oid ) {
355                 oir = (struct oindexrec *)
356                         ch_calloc( 1, sizeof(struct oindexrec) );
357                 oir->oir_name.bv_val = soc->soc_oid;
358                 oir->oir_name.bv_len = strlen( soc->soc_oid );
359                 oir->oir_oc = soc;
360
361                 assert( oir->oir_name.bv_val );
362                 assert( oir->oir_oc );
363
364                 if ( avl_insert( &oc_index, (caddr_t) oir,
365                                  oc_index_cmp, avl_dup_error ) )
366                 {
367                         *err = soc->soc_oid;
368                         ldap_memfree(oir);
369                         return SLAP_SCHERR_CLASS_DUP;
370                 }
371
372                 /* FIX: temporal consistency check */
373                 assert( oc_bvfind(&oir->oir_name) != NULL );
374         }
375
376         if ( (names = soc->soc_names) ) {
377                 while ( *names ) {
378                         oir = (struct oindexrec *)
379                                 ch_calloc( 1, sizeof(struct oindexrec) );
380                         oir->oir_name.bv_val = *names;
381                         oir->oir_name.bv_len = strlen( *names );
382                         oir->oir_oc = soc;
383
384                         assert( oir->oir_name.bv_val );
385                         assert( oir->oir_oc );
386
387                         if ( avl_insert( &oc_index, (caddr_t) oir,
388                                          oc_index_cmp, avl_dup_error ) )
389                         {
390                                 *err = *names;
391                                 ldap_memfree(oir);
392                                 return SLAP_SCHERR_CLASS_DUP;
393                         }
394
395                         /* FIX: temporal consistency check */
396                         assert( oc_bvfind(&oir->oir_name) != NULL );
397
398                         names++;
399                 }
400         }
401
402         return 0;
403 }
404
405 int
406 oc_add(
407     LDAPObjectClass     *oc,
408         int user,
409     const char          **err
410 )
411 {
412         ObjectClass     *soc;
413         int             code;
414         int             op = 0;
415
416         if ( oc->oc_names != NULL ) {
417                 int i;
418
419                 for( i=0; oc->oc_names[i]; i++ ) {
420                         if( !slap_valid_descr( oc->oc_names[i] ) ) {
421                                 return SLAP_SCHERR_BAD_DESCR;
422                         }
423                 }
424         }
425
426         if ( !OID_LEADCHAR( oc->oc_oid[0] )) {
427                 /* Expand OID macros */
428                 char *oid = oidm_find( oc->oc_oid );
429                 if ( !oid ) {
430                         *err = oc->oc_oid;
431                         return SLAP_SCHERR_OIDM;
432                 }
433                 if ( oid != oc->oc_oid ) {
434                         ldap_memfree( oc->oc_oid );
435                         oc->oc_oid = oid;
436                 }
437         }
438
439         soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
440         AC_MEMCPY( &soc->soc_oclass, oc, sizeof(LDAPObjectClass) );
441
442         if( oc->oc_names != NULL ) {
443                 soc->soc_cname.bv_val = soc->soc_names[0];
444         } else {
445                 soc->soc_cname.bv_val = soc->soc_oid;
446         }
447         soc->soc_cname.bv_len = strlen( soc->soc_cname.bv_val );
448
449         if( soc->soc_sup_oids == NULL &&
450                 soc->soc_kind == LDAP_SCHEMA_STRUCTURAL )
451         {
452                 /* structural object classes implicitly inherit from 'top' */
453                 static char *top_oids[] = { SLAPD_TOP_OID, NULL };
454                 code = oc_add_sups( soc, top_oids, &op, err );
455         } else {
456                 code = oc_add_sups( soc, soc->soc_sup_oids, &op, err );
457         }
458
459         if ( code != 0 ) return code;
460
461         code = oc_create_required( soc, soc->soc_at_oids_must, &op, err );
462         if ( code != 0 ) return code;
463
464         code = oc_create_allowed( soc, soc->soc_at_oids_may, &op, err );
465         if ( code != 0 ) return code;
466
467         if( user && op ) return SLAP_SCHERR_CLASS_BAD_SUP;
468
469         code = oc_insert(soc,err);
470         return code;
471 }
472
473 int
474 oc_schema_info( Entry *e )
475 {
476         struct berval   vals[2];
477         ObjectClass     *oc;
478
479         AttributeDescription *ad_objectClasses = slap_schema.si_ad_objectClasses;
480
481         vals[1].bv_val = NULL;
482
483         for ( oc = oc_list; oc; oc = oc->soc_next ) {
484                 if( oc->soc_flags & SLAP_OC_HIDE ) continue;
485
486                 if ( ldap_objectclass2bv( &oc->soc_oclass, vals ) == NULL ) {
487                         return -1;
488                 }
489
490 #if 0
491                 Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n",
492                (long) vals[0].bv_len, vals[0].bv_val, 0 );
493 #endif
494                 if( attr_merge( e, ad_objectClasses, vals ) )
495                         return -1;
496                 ldap_memfree( vals[0].bv_val );
497         }
498         return 0;
499 }