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