]> git.sur5r.net Git - openldap/blob - servers/slapd/at.c
Happy New Year!
[openldap] / servers / slapd / at.c
1 /* at.c - routines for dealing with attribute types */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/ctype.h>
22 #include <ac/errno.h>
23 #include <ac/socket.h>
24 #include <ac/string.h>
25 #include <ac/time.h>
26
27 #include "slap.h"
28
29
30 int is_at_syntax(
31         AttributeType *at,
32         const char *oid )
33 {
34         for( ; at != NULL; at = at->sat_sup ) {
35                 if( at->sat_syntax_oid ) {
36                         return ( strcmp( at->sat_syntax_oid, oid ) == 0 );
37                 }
38         }
39
40         return 0;
41 }
42
43 int is_at_subtype(
44         AttributeType *sub,
45         AttributeType *sup )
46 {
47         for( ; sub != NULL; sub = sub->sat_sup ) {
48                 if( sub == sup ) return 1;
49         }
50
51         return 0;
52 }
53
54 struct aindexrec {
55         struct berval   air_name;
56         AttributeType   *air_at;
57 };
58
59 static Avlnode  *attr_index = NULL;
60 static LDAP_SLIST_HEAD(ATList, slap_attribute_type) attr_list
61         = LDAP_SLIST_HEAD_INITIALIZER(&attr_list);
62
63 static int
64 attr_index_cmp(
65     const void  *v_air1,
66     const void  *v_air2 )
67 {
68         const struct aindexrec  *air1 = v_air1;
69         const struct aindexrec  *air2 = v_air2;
70         int i = air1->air_name.bv_len - air2->air_name.bv_len;
71         if (i) return i;
72         return (strcasecmp( air1->air_name.bv_val, air2->air_name.bv_val ));
73 }
74
75 static int
76 attr_index_name_cmp(
77     const void  *v_type,
78     const void  *v_air )
79 {
80     const struct berval    *type = v_type;
81     const struct aindexrec *air  = v_air;
82         int i = type->bv_len - air->air_name.bv_len;
83         if (i) return i;
84         return (strncasecmp( type->bv_val, air->air_name.bv_val, type->bv_len ));
85 }
86
87 AttributeType *
88 at_find( const char *name )
89 {
90         struct berval bv;
91
92         bv.bv_val = (char *)name;
93         bv.bv_len = strlen( name );
94
95         return at_bvfind( &bv );
96 }
97
98 AttributeType *
99 at_bvfind( struct berval *name )
100 {
101         struct aindexrec *air;
102
103         air = avl_find( attr_index, name, attr_index_name_cmp );
104
105         return air != NULL ? air->air_at : NULL;
106 }
107
108 int
109 at_append_to_list(
110     AttributeType       *sat,
111     AttributeType       ***listp )
112 {
113         AttributeType   **list;
114         AttributeType   **list1;
115         int             size;
116
117         list = *listp;
118         if ( !list ) {
119                 size = 2;
120                 list = ch_calloc(size, sizeof(AttributeType *));
121                 if ( !list ) {
122                         return -1;
123                 }
124         } else {
125                 size = 0;
126                 list1 = *listp;
127                 while ( *list1 ) {
128                         size++;
129                         list1++;
130                 }
131                 size += 2;
132                 list1 = ch_realloc(list, size*sizeof(AttributeType *));
133                 if ( !list1 ) {
134                         return -1;
135                 }
136                 list = list1;
137         }
138         list[size-2] = sat;
139         list[size-1] = NULL;
140         *listp = list;
141         return 0;
142 }
143
144 int
145 at_delete_from_list(
146     int                 pos,
147     AttributeType       ***listp )
148 {
149         AttributeType   **list;
150         AttributeType   **list1;
151         int             i;
152         int             j;
153
154         if ( pos < 0 ) {
155                 return -2;
156         }
157         list = *listp;
158         for ( i=0; list[i]; i++ )
159                 ;
160         if ( pos >= i ) {
161                 return -2;
162         }
163         for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
164                 list[i] = list[j];
165         }
166         list[i] = NULL;
167         /* Tell the runtime this can be shrinked */
168         list1 = ch_realloc(list, (i+1)*sizeof(AttributeType **));
169         if ( !list1 ) {
170                 return -1;
171         }
172         *listp = list1;
173         return 0;
174 }
175
176 int
177 at_find_in_list(
178     AttributeType       *sat,
179     AttributeType       **list )
180 {
181         int     i;
182
183         if ( !list ) {
184                 return -1;
185         }
186         for ( i=0; list[i]; i++ ) {
187                 if ( sat == list[i] ) {
188                         return i;
189                 }
190         }
191         return -1;
192 }
193
194 void
195 at_destroy( void )
196 {
197         AttributeType *a;
198         avl_free(attr_index, ldap_memfree);
199
200         while( !LDAP_SLIST_EMPTY(&attr_list) ) {
201                 a = LDAP_SLIST_FIRST(&attr_list);
202                 LDAP_SLIST_REMOVE_HEAD(&attr_list, sat_next);
203
204                 if (a->sat_subtypes) ldap_memfree(a->sat_subtypes);
205                 ad_destroy(a->sat_ad);
206                 ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex);
207                 ldap_attributetype_free((LDAPAttributeType *)a);
208         }
209
210         if ( slap_schema.si_at_undefined ) {
211                 ad_destroy(slap_schema.si_at_undefined->sat_ad);
212         }
213 }
214
215 int
216 at_start( AttributeType **at )
217 {
218         assert( at );
219
220         *at = LDAP_SLIST_FIRST(&attr_list);
221
222         return (*at != NULL);
223 }
224
225 int
226 at_next( AttributeType **at )
227 {
228         assert( at );
229
230 #if 1   /* pedantic check */
231         {
232                 AttributeType *tmp = NULL;
233
234                 LDAP_SLIST_FOREACH(tmp,&attr_list,sat_next) {
235                         if ( tmp == *at ) {
236                                 break;
237                         }
238                 }
239
240                 assert( tmp );
241         }
242 #endif
243
244         *at = LDAP_SLIST_NEXT(*at,sat_next);
245
246         return (*at != NULL);
247 }
248         
249
250
251 static int
252 at_insert(
253     AttributeType       *sat,
254     const char          **err )
255 {
256         struct aindexrec        *air;
257         char                    **names;
258
259         LDAP_SLIST_NEXT( sat, sat_next ) = NULL;
260         LDAP_SLIST_INSERT_HEAD( &attr_list, sat, sat_next );
261
262         if ( sat->sat_oid ) {
263                 air = (struct aindexrec *)
264                         ch_calloc( 1, sizeof(struct aindexrec) );
265                 air->air_name.bv_val = sat->sat_oid;
266                 air->air_name.bv_len = strlen(sat->sat_oid);
267                 air->air_at = sat;
268                 if ( avl_insert( &attr_index, (caddr_t) air,
269                                  attr_index_cmp, avl_dup_error ) ) {
270                         *err = sat->sat_oid;
271                         ldap_memfree(air);
272                         return SLAP_SCHERR_ATTR_DUP;
273                 }
274                 /* FIX: temporal consistency check */
275                 at_bvfind(&air->air_name);
276         }
277
278         if ( (names = sat->sat_names) ) {
279                 while ( *names ) {
280                         air = (struct aindexrec *)
281                                 ch_calloc( 1, sizeof(struct aindexrec) );
282                         air->air_name.bv_val = *names;
283                         air->air_name.bv_len = strlen(*names);
284                         air->air_at = sat;
285                         if ( avl_insert( &attr_index, (caddr_t) air,
286                                          attr_index_cmp, avl_dup_error ) ) {
287                                 *err = *names;
288                                 ldap_memfree(air);
289                                 return SLAP_SCHERR_ATTR_DUP;
290                         }
291                         /* FIX: temporal consistency check */
292                         at_bvfind(&air->air_name);
293                         names++;
294                 }
295         }
296
297         return 0;
298 }
299
300 int
301 at_add(
302     LDAPAttributeType   *at,
303     const char          **err )
304 {
305         AttributeType   *sat;
306         MatchingRule    *mr;
307         Syntax          *syn;
308         int             i;
309         int             code;
310         char    *cname;
311         char    *oid;
312
313         if ( !OID_LEADCHAR( at->at_oid[0] )) {
314                 /* Expand OID macros */
315                 oid = oidm_find( at->at_oid );
316                 if ( !oid ) {
317                         *err = at->at_oid;
318                         return SLAP_SCHERR_OIDM;
319                 }
320                 if ( oid != at->at_oid ) {
321                         ldap_memfree( at->at_oid );
322                         at->at_oid = oid;
323                 }
324         }
325
326         if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
327                 /* Expand OID macros */
328                 oid = oidm_find( at->at_syntax_oid );
329                 if ( !oid ) {
330                         *err = at->at_syntax_oid;
331                         return SLAP_SCHERR_OIDM;
332                 }
333                 if ( oid != at->at_syntax_oid ) {
334                         ldap_memfree( at->at_syntax_oid );
335                         at->at_syntax_oid = oid;
336                 }
337         }
338
339         if ( at->at_names && at->at_names[0] ) {
340                 int i;
341
342                 for( i=0; at->at_names[i]; i++ ) {
343                         if( !slap_valid_descr( at->at_names[i] ) ) {
344                                 *err = at->at_names[i];
345                                 return SLAP_SCHERR_BAD_DESCR;
346                         }
347                 }
348
349                 cname = at->at_names[0];
350
351         } else if ( at->at_oid ) {
352                 cname = at->at_oid;
353
354         } else {
355                 *err = "";
356                 return SLAP_SCHERR_ATTR_INCOMPLETE;
357         }
358
359         *err = cname;
360
361         if ( !at->at_usage && at->at_no_user_mod ) {
362                 /* user attribute must be modifable */
363                 return SLAP_SCHERR_ATTR_BAD_USAGE;
364         }
365
366         if ( at->at_collective ) {
367                 if( at->at_usage ) {
368                         /* collective attributes cannot be operational */
369                         return SLAP_SCHERR_ATTR_BAD_USAGE;
370                 }
371
372                 if( at->at_single_value ) {
373                         /* collective attributes cannot be single-valued */
374                         return SLAP_SCHERR_ATTR_BAD_USAGE;
375                 }
376         }
377
378         sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
379         AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType));
380
381         sat->sat_cname.bv_val = cname;
382         sat->sat_cname.bv_len = strlen( cname );
383         ldap_pvt_thread_mutex_init(&sat->sat_ad_mutex);
384
385         if ( at->at_sup_oid ) {
386                 AttributeType *supsat = at_find(at->at_sup_oid);
387
388                 if ( supsat == NULL ) {
389                         *err = at->at_sup_oid;
390                         return SLAP_SCHERR_ATTR_NOT_FOUND;
391                 }
392
393                 sat->sat_sup = supsat;
394
395                 if ( at_append_to_list(sat, &supsat->sat_subtypes) ) {
396                         return SLAP_SCHERR_OUTOFMEM;
397                 }
398
399                 if ( sat->sat_usage != supsat->sat_usage ) {
400                         /* subtypes must have same usage as their SUP */
401                         return SLAP_SCHERR_ATTR_BAD_USAGE;
402                 }
403
404                 if ( supsat->sat_obsolete && !sat->sat_obsolete ) {
405                         /* subtypes must be obsolete if super is */
406                         return SLAP_SCHERR_ATTR_BAD_SUP;
407                 }
408
409                 if ( sat->sat_flags & SLAP_AT_FINAL ) {
410                         /* cannot subtype a "final" attribute type */
411                         return SLAP_SCHERR_ATTR_BAD_SUP;
412                 }
413         }
414
415         /*
416          * Inherit definitions from superiors.  We only check the
417          * direct superior since that one has already inherited from
418          * its own superiorss
419          */
420         if ( sat->sat_sup ) {
421                 sat->sat_syntax = sat->sat_sup->sat_syntax;
422                 sat->sat_equality = sat->sat_sup->sat_equality;
423                 sat->sat_approx = sat->sat_sup->sat_approx;
424                 sat->sat_ordering = sat->sat_sup->sat_ordering;
425                 sat->sat_substr = sat->sat_sup->sat_substr;
426         }
427
428         if ( at->at_syntax_oid ) {
429                 syn = syn_find(sat->sat_syntax_oid);
430                 if ( syn == NULL ) {
431                         *err = sat->sat_syntax_oid;
432                         return SLAP_SCHERR_SYN_NOT_FOUND;
433                 }
434
435                 if( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
436                         return SLAP_SCHERR_ATTR_BAD_SUP;
437                 }
438
439                 sat->sat_syntax = syn;
440
441         } else if ( sat->sat_syntax == NULL ) {
442                 return SLAP_SCHERR_ATTR_INCOMPLETE;
443         }
444
445         if ( sat->sat_equality_oid ) {
446                 mr = mr_find(sat->sat_equality_oid);
447
448                 if( mr == NULL ) {
449                         *err = sat->sat_equality_oid;
450                         return SLAP_SCHERR_MR_NOT_FOUND;
451                 }
452
453                 if(( mr->smr_usage & SLAP_MR_EQUALITY ) != SLAP_MR_EQUALITY ) {
454                         *err = sat->sat_equality_oid;
455                         return SLAP_SCHERR_ATTR_BAD_MR;
456                 }
457
458                 if( sat->sat_syntax != mr->smr_syntax ) {
459                         if( mr->smr_compat_syntaxes == NULL ) {
460                                 *err = sat->sat_equality_oid;
461                                 return SLAP_SCHERR_ATTR_BAD_MR;
462                         }
463
464                         for(i=0; mr->smr_compat_syntaxes[i]; i++) {
465                                 if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) {
466                                         i = -1;
467                                         break;
468                                 }
469                         }
470
471                         if( i >= 0 ) {
472                                 *err = sat->sat_equality_oid;
473                                 return SLAP_SCHERR_ATTR_BAD_MR;
474                         }
475                 }
476
477                 sat->sat_equality = mr;
478                 sat->sat_approx = mr->smr_associated;
479         }
480
481         if ( sat->sat_ordering_oid ) {
482                 if( !sat->sat_equality ) {
483                         *err = sat->sat_ordering_oid;
484                         return SLAP_SCHERR_ATTR_BAD_MR;
485                 }
486
487                 mr = mr_find(sat->sat_ordering_oid);
488
489                 if( mr == NULL ) {
490                         *err = sat->sat_ordering_oid;
491                         return SLAP_SCHERR_MR_NOT_FOUND;
492                 }
493
494                 if(( mr->smr_usage & SLAP_MR_ORDERING ) != SLAP_MR_ORDERING ) {
495                         *err = sat->sat_ordering_oid;
496                         return SLAP_SCHERR_ATTR_BAD_MR;
497                 }
498
499                 if( sat->sat_syntax != mr->smr_syntax ) {
500                         if( mr->smr_compat_syntaxes == NULL ) {
501                                 *err = sat->sat_ordering_oid;
502                                 return SLAP_SCHERR_ATTR_BAD_MR;
503                         }
504
505                         for(i=0; mr->smr_compat_syntaxes[i]; i++) {
506                                 if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) {
507                                         i = -1;
508                                         break;
509                                 }
510                         }
511
512                         if( i >= 0 ) {
513                                 *err = sat->sat_ordering_oid;
514                                 return SLAP_SCHERR_ATTR_BAD_MR;
515                         }
516                 }
517
518                 sat->sat_ordering = mr;
519         }
520
521         if ( sat->sat_substr_oid ) {
522                 if( !sat->sat_equality ) {
523                         *err = sat->sat_substr_oid;
524                         return SLAP_SCHERR_ATTR_BAD_MR;
525                 }
526
527                 mr = mr_find(sat->sat_substr_oid);
528
529                 if( mr == NULL ) {
530                         *err = sat->sat_substr_oid;
531                         return SLAP_SCHERR_MR_NOT_FOUND;
532                 }
533
534                 if(( mr->smr_usage & SLAP_MR_SUBSTR ) != SLAP_MR_SUBSTR ) {
535                         *err = sat->sat_substr_oid;
536                         return SLAP_SCHERR_ATTR_BAD_MR;
537                 }
538
539                 /* due to funky LDAP builtin substring rules,
540                  * we check against the equality rule assertion
541                  * syntax and compat syntaxes instead of those
542                  * associated with the substrings rule.
543                  */
544                 if( sat->sat_syntax != sat->sat_equality->smr_syntax ) {
545                         if( sat->sat_equality->smr_compat_syntaxes == NULL ) {
546                                 *err = sat->sat_substr_oid;
547                                 return SLAP_SCHERR_ATTR_BAD_MR;
548                         }
549
550                         for(i=0; sat->sat_equality->smr_compat_syntaxes[i]; i++) {
551                                 if( sat->sat_syntax ==
552                                         sat->sat_equality->smr_compat_syntaxes[i] )
553                                 {
554                                         i = -1;
555                                         break;
556                                 }
557                         }
558
559                         if( i >= 0 ) {
560                                 *err = sat->sat_substr_oid;
561                                 return SLAP_SCHERR_ATTR_BAD_MR;
562                         }
563                 }
564
565                 sat->sat_substr = mr;
566         }
567
568         code = at_insert(sat,err);
569         return code;
570 }
571
572 #ifdef LDAP_DEBUG
573 static int
574 at_index_printnode( void *v_air, void *ignore )
575 {
576         struct aindexrec *air = v_air;
577         printf("%s = %s\n",
578                 air->air_name.bv_val,
579                 ldap_attributetype2str(&air->air_at->sat_atype) );
580         return( 0 );
581 }
582
583 static void
584 at_index_print( void )
585 {
586         printf("Printing attribute type index:\n");
587         (void) avl_apply( attr_index, at_index_printnode, 0, -1, AVL_INORDER );
588 }
589 #endif
590
591 int
592 at_schema_info( Entry *e )
593 {
594         AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes;
595         AttributeType   *at;
596         struct berval   val;
597         struct berval   nval;
598
599         LDAP_SLIST_FOREACH(at,&attr_list,sat_next) {
600                 if( at->sat_flags & SLAP_AT_HIDE ) continue;
601
602                 if ( ldap_attributetype2bv( &at->sat_atype, &val ) == NULL ) {
603                         return -1;
604                 }
605
606                 nval.bv_val = at->sat_oid;
607                 nval.bv_len = strlen(at->sat_oid);
608
609                 if( attr_merge_one( e, ad_attributeTypes, &val, &nval ) )
610                 {
611                         return -1;
612                 }
613                 ldap_memfree( val.bv_val );
614         }
615         return 0;
616 }