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