]> git.sur5r.net Git - openldap/blob - servers/slapd/oc.c
8c185e07e50841c32bc9635e789f5849d732d567
[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_object_subclass(
20         ObjectClass *sub,
21         ObjectClass *sup )
22 {
23         int i;
24
25         if( sup == sub ) {
26                 return 1;
27         }
28
29         if( sup->soc_sups == NULL ) {
30                 return 0;
31         }
32
33         for( i=0; sup->soc_sups[i] != NULL; i++ ) {
34                 if( is_object_subclass( sup->soc_sups[i], sup ) ) {
35                         return 1;
36                 }
37         }
38
39         return 0;
40 }
41
42 int is_entry_objectclass(
43         Entry*  e,
44         ObjectClass *oc
45 )
46 {
47         Attribute *attr;
48         int i;
49         AttributeDescription *objectClass = slap_schema.si_ad_objectClass;
50         assert(!( e == NULL || oc == NULL ));
51
52         if( e == NULL || oc == NULL ) {
53                 return 0;
54         }
55
56         /*
57          * find objectClass attribute
58          */
59         attr = attr_find(e->e_attrs, objectClass);
60
61         if( attr == NULL ) {
62                 /* no objectClass attribute */
63                 Debug( LDAP_DEBUG_ANY, "is_entry_objectclass(\"%s\", \"%s\") "
64                         "no objectClass attribute\n",
65                         e->e_dn == NULL ? "" : e->e_dn,
66                         oc->soc_oclass.oc_oid, 0 );
67
68                 return 0;
69         }
70
71         for( i=0; attr->a_vals[i]; i++ ) {
72                 ObjectClass *objectClass = oc_find( attr->a_vals[i]->bv_val );
73
74                 if( objectClass == oc ) {
75                         return 1;
76                 }
77         }
78
79         return 0;
80
81 }
82
83
84
85
86 struct oindexrec {
87         char            *oir_name;
88         ObjectClass     *oir_oc;
89 };
90
91 static Avlnode  *oc_index = NULL;
92 static ObjectClass *oc_list = NULL;
93
94 static int
95 oc_index_cmp(
96     struct oindexrec    *oir1,
97     struct oindexrec    *oir2
98 )
99 {
100         assert( oir1->oir_name );
101         assert( oir1->oir_oc );
102         assert( oir2->oir_name );
103         assert( oir2->oir_oc );
104
105         return (strcasecmp( oir1->oir_name, oir2->oir_name ));
106 }
107
108 static int
109 oc_index_name_cmp(
110     char                *name,
111     struct oindexrec    *oir
112 )
113 {
114         assert( oir->oir_name );
115         assert( oir->oir_oc );
116
117         return (strcasecmp( name, oir->oir_name ));
118 }
119
120 ObjectClass *
121 oc_find( const char *ocname )
122 {
123         struct oindexrec        *oir;
124
125         oir = (struct oindexrec *) avl_find( oc_index, ocname,
126             (AVL_CMP) oc_index_name_cmp );
127
128         if ( oir != NULL ) {
129                 assert( oir->oir_name );
130                 assert( oir->oir_oc );
131
132                 return( oir->oir_oc );
133         }
134
135         return( NULL );
136 }
137
138 static int
139 oc_create_required(
140     ObjectClass         *soc,
141     char                **attrs,
142     const char          **err
143 )
144 {
145         char            **attrs1;
146         AttributeType   *sat;
147         AttributeType   **satp;
148         int             i;
149
150         if ( attrs ) {
151                 attrs1 = attrs;
152                 while ( *attrs1 ) {
153                         sat = at_find(*attrs1);
154                         if ( !sat ) {
155                                 *err = *attrs1;
156                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
157                         }
158                         if ( at_find_in_list(sat, soc->soc_required) < 0) {
159                                 if ( at_append_to_list(sat, &soc->soc_required) ) {
160                                         *err = *attrs1;
161                                         return SLAP_SCHERR_OUTOFMEM;
162                                 }
163                         }
164                         attrs1++;
165                 }
166                 /* Now delete duplicates from the allowed list */
167                 for ( satp = soc->soc_required; *satp; satp++ ) {
168                         i = at_find_in_list(*satp,soc->soc_allowed);
169                         if ( i >= 0 ) {
170                                 at_delete_from_list(i, &soc->soc_allowed);
171                         }
172                 }
173         }
174         return 0;
175 }
176
177 static int
178 oc_create_allowed(
179     ObjectClass         *soc,
180     char                **attrs,
181     const char          **err
182 )
183 {
184         char            **attrs1;
185         AttributeType   *sat;
186
187         if ( attrs ) {
188                 attrs1 = attrs;
189                 while ( *attrs1 ) {
190                         sat = at_find(*attrs1);
191                         if ( !sat ) {
192                                 *err = *attrs1;
193                                 return SLAP_SCHERR_ATTR_NOT_FOUND;
194                         }
195                         if ( at_find_in_list(sat, soc->soc_required) < 0 &&
196                              at_find_in_list(sat, soc->soc_allowed) < 0 ) {
197                                 if ( at_append_to_list(sat, &soc->soc_allowed) ) {
198                                         *err = *attrs1;
199                                         return SLAP_SCHERR_OUTOFMEM;
200                                 }
201                         }
202                         attrs1++;
203                 }
204         }
205         return 0;
206 }
207
208 static int
209 oc_add_sups(
210     ObjectClass         *soc,
211     char                **sups,
212     const char          **err
213 )
214 {
215         int             code;
216         ObjectClass     *soc1;
217         int             nsups;
218         char            **sups1;
219         int             add_sups = 0;
220
221         if ( sups ) {
222                 if ( !soc->soc_sups ) {
223                         /* We are at the first recursive level */
224                         add_sups = 1;
225                         nsups = 0;
226                         sups1 = sups;
227                         while ( *sups1 ) {
228                                 nsups++;
229                                 sups1++;
230                         }
231                         nsups++;
232                         soc->soc_sups = (ObjectClass **)ch_calloc(nsups,
233                                           sizeof(ObjectClass *));
234                 }
235                 nsups = 0;
236                 sups1 = sups;
237                 while ( *sups1 ) {
238                         soc1 = oc_find(*sups1);
239                         if ( !soc1 ) {
240                                 *err = *sups1;
241                                 return SLAP_SCHERR_CLASS_NOT_FOUND;
242                         }
243
244                         if ( add_sups )
245                                 soc->soc_sups[nsups] = soc1;
246
247                         code = oc_add_sups(soc,soc1->soc_sup_oids, err);
248                         if ( code )
249                                 return code;
250
251                         code = oc_create_required(soc,soc1->soc_at_oids_must,err);
252                         if ( code )
253                                 return code;
254                         code = oc_create_allowed(soc,soc1->soc_at_oids_may,err);
255                         if ( code )
256                                 return code;
257
258                         nsups++;
259                         sups1++;
260                 }
261         }
262         return 0;
263 }
264
265 static int
266 oc_insert(
267     ObjectClass         *soc,
268     const char          **err
269 )
270 {
271         ObjectClass     **ocp;
272         struct oindexrec        *oir;
273         char                    **names;
274
275         ocp = &oc_list;
276         while ( *ocp != NULL ) {
277                 ocp = &(*ocp)->soc_next;
278         }
279         *ocp = soc;
280
281         if ( soc->soc_oid ) {
282                 oir = (struct oindexrec *)
283                         ch_calloc( 1, sizeof(struct oindexrec) );
284                 oir->oir_name = soc->soc_oid;
285                 oir->oir_oc = soc;
286
287                 assert( oir->oir_name );
288                 assert( oir->oir_oc );
289
290                 if ( avl_insert( &oc_index, (caddr_t) oir,
291                                  (AVL_CMP) oc_index_cmp,
292                                  (AVL_DUP) avl_dup_error ) )
293                 {
294                         *err = soc->soc_oid;
295                         ldap_memfree(oir->oir_name);
296                         ldap_memfree(oir);
297                         return SLAP_SCHERR_DUP_CLASS;
298                 }
299
300                 /* FIX: temporal consistency check */
301                 assert( oc_find(oir->oir_name) != NULL );
302         }
303
304         if ( (names = soc->soc_names) ) {
305                 while ( *names ) {
306                         oir = (struct oindexrec *)
307                                 ch_calloc( 1, sizeof(struct oindexrec) );
308                         oir->oir_name = ch_strdup(*names);
309                         oir->oir_oc = soc;
310
311                         assert( oir->oir_name );
312                         assert( oir->oir_oc );
313
314                         if ( avl_insert( &oc_index, (caddr_t) oir,
315                                          (AVL_CMP) oc_index_cmp,
316                                          (AVL_DUP) avl_dup_error ) )
317                         {
318                                 *err = *names;
319                                 ldap_memfree(oir->oir_name);
320                                 ldap_memfree(oir);
321                                 return SLAP_SCHERR_DUP_CLASS;
322                         }
323
324                         /* FIX: temporal consistency check */
325                         assert( oc_find(oir->oir_name) != NULL );
326
327                         names++;
328                 }
329         }
330
331         return 0;
332 }
333
334 int
335 oc_add(
336     LDAP_OBJECT_CLASS   *oc,
337     const char          **err
338 )
339 {
340         ObjectClass     *soc;
341         int             code;
342
343         soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
344         memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
345         if ( (code = oc_add_sups(soc,soc->soc_sup_oids,err)) != 0 )
346                 return code;
347         if ( (code = oc_create_required(soc,soc->soc_at_oids_must,err)) != 0 )
348                 return code;
349         if ( (code = oc_create_allowed(soc,soc->soc_at_oids_may,err)) != 0 )
350                 return code;
351         code = oc_insert(soc,err);
352         return code;
353 }
354
355 #ifdef LDAP_DEBUG
356
357 static void
358 oc_print( ObjectClass *oc )
359 {
360         int     i;
361         const char *mid;
362
363         printf( "objectclass %s\n", ldap_objectclass2name( &oc->soc_oclass ) );
364         if ( oc->soc_required != NULL ) {
365                 mid = "\trequires ";
366                 for ( i = 0; oc->soc_required[i] != NULL; i++, mid = "," )
367                         printf( "%s%s", mid,
368                                 ldap_attributetype2name( &oc->soc_required[i]->sat_atype ) );
369                 printf( "\n" );
370         }
371         if ( oc->soc_allowed != NULL ) {
372                 mid = "\tallows ";
373                 for ( i = 0; oc->soc_allowed[i] != NULL; i++, mid = "," )
374                         printf( "%s%s", mid,
375                                 ldap_attributetype2name( &oc->soc_allowed[i]->sat_atype ) );
376                 printf( "\n" );
377         }
378 }
379
380 #endif
381
382
383 #if defined( SLAPD_SCHEMA_DN )
384
385 int
386 oc_schema_info( Entry *e )
387 {
388         struct berval   val;
389         struct berval   *vals[2];
390         ObjectClass     *oc;
391
392         AttributeDescription *ad_objectClasses = slap_schema.si_ad_objectClasses;
393
394         vals[0] = &val;
395         vals[1] = NULL;
396
397         for ( oc = oc_list; oc; oc = oc->soc_next ) {
398                 val.bv_val = ldap_objectclass2str( &oc->soc_oclass );
399                 if ( val.bv_val == NULL ) {
400                         return -1;
401                 }
402                 val.bv_len = strlen( val.bv_val );
403 #if 0
404                 Debug( LDAP_DEBUG_TRACE, "Merging oc [%ld] %s\n",
405                (long) val.bv_len, val.bv_val, 0 );
406 #endif
407                 attr_merge( e, ad_objectClasses, vals );
408                 ldap_memfree( val.bv_val );
409         }
410         return 0;
411 }
412
413 #endif