]> git.sur5r.net Git - openldap/blob - servers/slapd/attr.c
9bde8bc6b76c2bb75d00a3918a85bc6cbace1530
[openldap] / servers / slapd / attr.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5 /* attr.c - routines for dealing with attributes */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #ifdef HAVE_FCNTL_H
12 #include <fcntl.h>
13 #endif
14
15 #include <ac/ctype.h>
16 #include <ac/errno.h>
17 #include <ac/socket.h>
18 #include <ac/string.h>
19 #include <ac/time.h>
20
21 #ifdef HAVE_SYS_PARAM_H
22 #include <sys/param.h>
23 #endif
24
25 #include "ldap_defaults.h"
26 #include "slap.h"
27
28 #ifdef LDAP_DEBUG
29 static void at_index_print( void );
30 #endif
31
32 void
33 attr_free( Attribute *a )
34 {
35         free( a->a_type );
36         ber_bvecfree( a->a_vals );
37         free( a );
38 }
39
40 void
41 attrs_free( Attribute *a )
42 {
43         Attribute *next;
44
45         for( ; a != NULL ; a = next ) {
46                 next = a->a_next;
47                 attr_free( a );
48         }
49 }
50
51 Attribute *attr_dup( Attribute *a )
52 {
53         Attribute *tmp;
54
55         if( a == NULL) return NULL;
56
57         tmp = ch_malloc( sizeof(Attribute) );
58
59         if( a->a_vals != NULL ) {
60                 int i;
61
62                 for( i=0; a->a_vals[i] != NULL; i++ ) {
63                         /* EMPTY */ ;
64                 }
65
66                 tmp->a_vals = ch_malloc((i+1) * sizeof(struct berval*));
67
68                 for( i=0; a->a_vals[i] != NULL; i++ ) {
69                         tmp->a_vals[i] = ber_bvdup( a->a_vals[i] );
70
71                         if( tmp->a_vals[i] == NULL ) break;
72                 }
73
74                 tmp->a_vals[i] = NULL;
75
76         } else {
77                 tmp->a_vals = NULL;
78         }
79
80         tmp->a_type = ch_strdup( a->a_type );
81         tmp->a_syntax = a->a_syntax;
82         tmp->a_next = NULL;
83
84         return tmp;
85 }
86
87 Attribute *attrs_dup( Attribute *a )
88 {
89         Attribute *tmp, **next;
90
91         if( a == NULL ) return NULL;
92
93         tmp = NULL;
94         next = &tmp;
95
96         for( ; a != NULL ; a = a->a_next ) {
97                 *next = attr_dup( a );
98                 next = &((*next)->a_next);
99         }
100         *next = NULL;
101
102         return tmp;
103 }
104
105 /*
106  * attr_normalize - normalize an attribute name (make it all lowercase)
107  */
108
109 char *
110 attr_normalize( char *s )
111 {
112         assert( s != NULL );
113
114         return( str2lower( s ) );
115 }
116
117 /*
118  * attr_merge_fast - merge the given type and value with the list of
119  * attributes in attrs. called from str2entry(), where we can make some
120  * assumptions to make things faster.
121  * returns      0       everything went ok
122  *              -1      trouble
123  */
124
125 int
126 attr_merge_fast(
127     Entry               *e,
128     char                *type,
129     struct berval       **vals,
130     int                 nvals,
131     int                 naddvals,
132     int                 *maxvals,
133     Attribute           ***a
134 )
135 {
136         if ( *a == NULL ) {
137                 for ( *a = &e->e_attrs; **a != NULL; *a = &(**a)->a_next ) {
138                         if ( strcasecmp( (**a)->a_type, type ) == 0 ) {
139                                 break;
140                         }
141                 }
142         }
143
144         if ( **a == NULL ) {
145                 **a = (Attribute *) ch_malloc( sizeof(Attribute) );
146                 (**a)->a_type = attr_normalize( ch_strdup( type ) );
147                 (**a)->a_vals = NULL;
148                 (**a)->a_syntax = attr_syntax( type );
149                 (**a)->a_next = NULL;
150         }
151
152         return( value_add_fast( &(**a)->a_vals, vals, nvals, naddvals,
153             maxvals ) );
154 }
155
156 /*
157  * attr_merge - merge the given type and value with the list of
158  * attributes in attrs.
159  * returns      0       everything went ok
160  *              -1      trouble
161  */
162
163 int
164 attr_merge(
165     Entry               *e,
166     char                *type,
167     struct berval       **vals
168 )
169 {
170         Attribute       **a;
171
172         for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
173                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
174                         break;
175                 }
176         }
177
178         if ( *a == NULL ) {
179                 *a = (Attribute *) ch_malloc( sizeof(Attribute) );
180                 (*a)->a_type = attr_normalize( ch_strdup( type ) );
181                 (*a)->a_vals = NULL;
182                 (*a)->a_syntax = attr_syntax( type );
183                 (*a)->a_next = NULL;
184         }
185
186         return( value_add( &(*a)->a_vals, vals ) );
187 }
188
189 /*
190  * attr_find - find and return attribute type in list a
191  */
192
193 Attribute *
194 attr_find(
195     Attribute   *a,
196     const char  *type
197 )
198 {
199         for ( ; a != NULL; a = a->a_next ) {
200                 if ( strcasecmp( a->a_type, type ) == 0 ) {
201                         return( a );
202                 }
203         }
204
205         return( NULL );
206 }
207
208 /*
209  * attr_delete - delete the attribute type in list pointed to by attrs
210  * return       0       deleted ok
211  *              1       not found in list a
212  *              -1      something bad happened
213  */
214
215 int
216 attr_delete(
217     Attribute   **attrs,
218     const char  *type
219 )
220 {
221         Attribute       **a;
222         Attribute       *save;
223
224         for ( a = attrs; *a != NULL; a = &(*a)->a_next ) {
225                 if ( strcasecmp( (*a)->a_type, type ) == 0 ) {
226                         break;
227                 }
228         }
229
230         if ( *a == NULL ) {
231                 return( 1 );
232         }
233
234         save = *a;
235         *a = (*a)->a_next;
236         attr_free( save );
237
238         return( 0 );
239 }
240
241 #define DEFAULT_SYNTAX  SYNTAX_CIS
242
243 /*
244  * attr_syntax - return the syntax of attribute type
245  */
246
247 int
248 attr_syntax( char *type )
249 {
250         AttributeType   *sat;
251
252         sat = at_find(type);
253         if ( sat ) {
254                 return( sat->sat_syntax_compat );
255         }
256
257         return( DEFAULT_SYNTAX );
258 }
259
260 /*
261  * attr_syntax_config - process an attribute syntax config line
262  */
263
264 void
265 attr_syntax_config(
266     const char  *fname,
267     int         lineno,
268     int         argc,
269     char        **argv
270 )
271 {
272         char                    *save;
273         LDAP_ATTRIBUTE_TYPE     *at;
274         int                     lasti;
275         int                     code;
276         const char              *err;
277
278         if ( argc < 2 ) {
279                 Debug( LDAP_DEBUG_ANY,
280 "%s: line %d: missing name in \"attribute <name>+ <syntax>\" (ignored)\n",
281                     fname, lineno, 0 );
282                 return;
283         }
284
285         at = (LDAP_ATTRIBUTE_TYPE *)
286                 ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) );
287
288         lasti = argc - 1;
289         if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 ||
290             strcasecmp( argv[lasti], "cis" ) == 0 ) {
291                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
292                 at->at_equality_oid = "2.5.13.2";
293                 at->at_ordering_oid = "2.5.13.3";
294                 at->at_substr_oid = "2.5.13.4";
295         } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
296             strcasecmp( argv[lasti], "tel" ) == 0 ) {
297                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.50";
298                 at->at_equality_oid = "2.5.13.20";
299                 at->at_substr_oid = "2.5.13.21";
300         } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
301                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.12";
302                 at->at_equality_oid = "2.5.13.1";
303         } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
304             strcasecmp( argv[lasti], "ces" ) == 0 ) {
305                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
306                 at->at_equality_oid = "2.5.13.5";
307                 at->at_ordering_oid = "2.5.13.6";
308                 at->at_substr_oid = "2.5.13.7";
309         } else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
310             strcasecmp( argv[lasti], "bin" ) == 0 ) {
311                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.5";
312                 /* There is no match for binary syntax. Really */
313         } else {
314                 Debug( LDAP_DEBUG_ANY,
315             "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
316                     fname, lineno, argv[lasti] );
317                 Debug( LDAP_DEBUG_ANY,
318     "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
319                     0, 0, 0 );
320                 free( (AttributeType *) at );
321                 return;
322         }
323
324         save = argv[lasti];
325         argv[lasti] = NULL;
326         at->at_names = charray_dup( argv );
327         argv[lasti] = save;
328
329         code = at_add( at, &err );
330         if ( code ) {
331                 fprintf( stderr, "%s: line %d: %s %s\n",
332                          fname, lineno, scherr2str(code), err);
333                 exit( EXIT_FAILURE );
334         }
335         ldap_memfree(at);
336 }
337
338 int
339 at_fake_if_needed(
340     char        *name
341 )
342 {
343         char *argv[3];
344
345         if ( at_find( name ) ) {
346                 return 0;
347         } else {
348                 argv[0] = name;
349                 argv[1] = "cis";
350                 argv[2] = NULL;
351                 attr_syntax_config( "implicit", 0, 2, argv );
352                 return 0;
353         }
354 }
355
356 struct aindexrec {
357         char            *air_name;
358         AttributeType   *air_at;
359 };
360
361 static Avlnode  *attr_index = NULL;
362 static AttributeType *attr_list = NULL;
363
364 static int
365 attr_index_cmp(
366     struct aindexrec    *air1,
367     struct aindexrec    *air2
368 )
369 {
370         return (strcasecmp( air1->air_name, air2->air_name ));
371 }
372
373 static int
374 attr_index_name_cmp(
375     char                *type,
376     struct aindexrec    *air
377 )
378 {
379         return (strcasecmp( type, air->air_name ));
380 }
381
382 AttributeType *
383 at_find(
384     const char          *name
385 )
386 {
387         struct aindexrec        *air = NULL;
388
389         if ( (air = (struct aindexrec *) avl_find( attr_index, name,
390             (AVL_CMP) attr_index_name_cmp )) != NULL ) {
391                 return( air->air_at );
392         }
393         return( NULL );
394 }
395
396 int
397 at_append_to_list(
398     AttributeType       *sat,
399     AttributeType       ***listp
400 )
401 {
402         AttributeType   **list;
403         AttributeType   **list1;
404         int             size;
405
406         list = *listp;
407         if ( !list ) {
408                 size = 2;
409                 list = calloc(size, sizeof(AttributeType *));
410                 if ( !list ) {
411                         return -1;
412                 }
413         } else {
414                 size = 0;
415                 list1 = *listp;
416                 while ( *list1 ) {
417                         size++;
418                         list1++;
419                 }
420                 size += 2;
421                 list1 = realloc(list, size*sizeof(AttributeType *));
422                 if ( !list1 ) {
423                         return -1;
424                 }
425                 list = list1;
426         }
427         list[size-2] = sat;
428         list[size-1] = NULL;
429         *listp = list;
430         return 0;
431 }
432
433 int
434 at_delete_from_list(
435     int                 pos,
436     AttributeType       ***listp
437 )
438 {
439         AttributeType   **list;
440         AttributeType   **list1;
441         int             i;
442         int             j;
443
444         if ( pos < 0 ) {
445                 return -2;
446         }
447         list = *listp;
448         for ( i=0; list[i]; i++ )
449                 ;
450         if ( pos >= i ) {
451                 return -2;
452         }
453         for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
454                 list[i] = list[j];
455         }
456         list[i] = NULL;
457         /* Tell the runtime this can be shrinked */
458         list1 = realloc(list, (i+1)*sizeof(AttributeType **));
459         if ( !list1 ) {
460                 return -1;
461         }
462         *listp = list1;
463         return 0;
464 }
465
466 int
467 at_find_in_list(
468     AttributeType       *sat,
469     AttributeType       **list
470 )
471 {
472         int     i;
473
474         if ( !list ) {
475                 return -1;
476         }
477         for ( i=0; list[i]; i++ ) {
478                 if ( sat == list[i] ) {
479                         return i;
480                 }
481         }
482         return -1;
483 }
484
485 static int
486 at_insert(
487     AttributeType       *sat,
488     const char          **err
489 )
490 {
491         AttributeType           **atp;
492         struct aindexrec        *air;
493         char                    **names;
494
495         atp = &attr_list;
496         while ( *atp != NULL ) {
497                 atp = &(*atp)->sat_next;
498         }
499         *atp = sat;
500
501         if ( sat->sat_oid ) {
502                 air = (struct aindexrec *)
503                         ch_calloc( 1, sizeof(struct aindexrec) );
504                 air->air_name = sat->sat_oid;
505                 air->air_at = sat;
506                 if ( avl_insert( &attr_index, (caddr_t) air,
507                                  (AVL_CMP) attr_index_cmp,
508                                  (AVL_DUP) avl_dup_error ) ) {
509                         *err = sat->sat_oid;
510                         ldap_memfree(air);
511                         return SLAP_SCHERR_DUP_ATTR;
512                 }
513                 /* FIX: temporal consistency check */
514                 at_find(air->air_name);
515         }
516         if ( (names = sat->sat_names) ) {
517                 while ( *names ) {
518                         air = (struct aindexrec *)
519                                 ch_calloc( 1, sizeof(struct aindexrec) );
520                         air->air_name = ch_strdup(*names);
521                         air->air_at = sat;
522                         if ( avl_insert( &attr_index, (caddr_t) air,
523                                          (AVL_CMP) attr_index_cmp,
524                                          (AVL_DUP) avl_dup_error ) ) {
525                                 *err = *names;
526                                 ldap_memfree(air);
527                                 return SLAP_SCHERR_DUP_ATTR;
528                         }
529                         /* FIX: temporal consistency check */
530                         at_find(air->air_name);
531                         names++;
532                 }
533         }
534
535         return 0;
536 }
537
538 int
539 at_add(
540     LDAP_ATTRIBUTE_TYPE *at,
541     const char          **err
542 )
543 {
544         AttributeType   *sat;
545         AttributeType   *sat1;
546         MatchingRule    *mr;
547         Syntax          *syn;
548         int             code;
549         char            *errattr;
550
551         if ( at->at_names && at->at_names[0] ) {
552                 errattr = at->at_names[0];
553         } else if ( at->at_oid ) {
554                 errattr = at->at_oid;
555         } else {
556                 errattr = "";
557                 return SLAP_SCHERR_ATTR_INCOMPLETE;
558         }
559         sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
560         memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE));
561         if ( at->at_sup_oid ) {
562                 if ( (sat1 = at_find(at->at_sup_oid)) ) {
563                         sat->sat_sup = sat1;
564                         if ( at_append_to_list(sat, &sat1->sat_subtypes) ) {
565                                 *err = errattr;
566                                 return SLAP_SCHERR_OUTOFMEM;
567                         }
568                 } else {
569                         *err = at->at_sup_oid;
570                         return SLAP_SCHERR_ATTR_NOT_FOUND;
571                 }
572         }
573
574         if ( at->at_syntax_oid ) {
575                 if ( (syn = syn_find(sat->sat_syntax_oid)) ) {
576                         sat->sat_syntax = syn;
577                 } else {
578                         *err = sat->sat_syntax_oid;
579                         return SLAP_SCHERR_SYN_NOT_FOUND;
580                 }
581                 if ( !strcmp(at->at_syntax_oid,
582                              "1.3.6.1.4.1.1466.115.121.1.15") ) {
583                         if ( at->at_equality_oid &&
584                              !strcmp(at->at_equality_oid, "2.5.13.5") ) {
585                                 sat->sat_syntax_compat = SYNTAX_CES;
586                         } else {
587                                 sat->sat_syntax_compat = SYNTAX_CIS;
588                         }
589                 } else if ( !strcmp(at->at_syntax_oid,
590                                     "1.3.6.1.4.1.1466.115.121.1.50") ) {
591                         sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL;
592                 } else if ( !strcmp(at->at_syntax_oid,
593                                     "1.3.6.1.4.1.1466.115.121.1.12") ) {
594                         sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN;
595                 } else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) {
596                         sat->sat_syntax_compat = SYNTAX_BIN;
597                 } else {
598                         sat->sat_syntax_compat = DEFAULT_SYNTAX;
599                 }
600         } else {
601                 sat->sat_syntax_compat = DEFAULT_SYNTAX;
602         }
603
604         if ( sat->sat_equality_oid ) {
605                 if ( (mr = mr_find(sat->sat_equality_oid)) ) {
606                         sat->sat_equality = mr;
607                 } else {
608                         *err = sat->sat_equality_oid;
609                         return SLAP_SCHERR_MR_NOT_FOUND;
610                 }
611         }
612         if ( sat->sat_ordering_oid ) {
613                 if ( (mr = mr_find(sat->sat_ordering_oid)) ) {
614                         sat->sat_ordering = mr;
615                 } else {
616                         *err = sat->sat_ordering_oid;
617                         return SLAP_SCHERR_MR_NOT_FOUND;
618                 }
619         }
620         if ( sat->sat_substr_oid ) {
621                 if ( (mr = mr_find(sat->sat_substr_oid)) ) {
622                         sat->sat_substr = mr;
623                 } else {
624                         *err = sat->sat_substr_oid;
625                         return SLAP_SCHERR_MR_NOT_FOUND;
626                 }
627         }
628
629         /*
630          * Now inherit definitions from superiors.  We only check the
631          * direct superior since that one has already inherited from
632          * its own superiorss
633          */
634         if ( sat->sat_sup ) {
635                 if ( !sat->sat_syntax ) {
636                         sat->sat_syntax = sat->sat_sup->sat_syntax;
637                         sat->sat_syntax_len = sat->sat_sup->sat_syntax_len;
638                 }
639                 if ( !sat->sat_equality ) {
640                         sat->sat_equality = sat->sat_sup->sat_equality;
641                 }
642                 if ( !sat->sat_ordering ) {
643                         sat->sat_ordering = sat->sat_sup->sat_ordering;
644                 }
645                 if ( !sat->sat_substr ) {
646                         sat->sat_substr = sat->sat_sup->sat_substr;
647                 }
648         }
649         code = at_insert(sat,err);
650         return code;
651 }
652
653
654 char *
655 at_canonical_name( char * a_type )
656 {
657         AttributeType   *atp;
658
659         if ( (atp=at_find(a_type)) == NULL ) {
660
661                 return a_type;
662
663         } else  if ( atp->sat_names 
664                      && atp->sat_names[0]
665                      && (*(atp->sat_names[0]) != '\0') ) {
666             
667                 return atp->sat_names[0];
668
669         } else if (atp->sat_oid && (*atp->sat_oid != '\0')) {
670
671                 return atp->sat_oid;
672                 
673         } else {
674
675                 return a_type;
676
677         }
678
679 }/* char * at_canonica_name() */
680
681
682 #if defined( SLAPD_SCHEMA_DN )
683
684 int
685 at_schema_info( Entry *e )
686 {
687         struct berval   val;
688         struct berval   *vals[2];
689         AttributeType   *at;
690
691         vals[0] = &val;
692         vals[1] = NULL;
693
694         for ( at = attr_list; at; at = at->sat_next ) {
695                 val.bv_val = ldap_attributetype2str( &at->sat_atype );
696                 if ( val.bv_val ) {
697                         val.bv_len = strlen( val.bv_val );
698                         Debug( LDAP_DEBUG_TRACE, "Merging at [%d] %s\n",
699                                val.bv_len, val.bv_val, 0 );
700                         attr_merge( e, "attributeTypes", vals );
701                         ldap_memfree( val.bv_val );
702                 } else {
703                         return -1;
704                 }
705         }
706         return 0;
707 }
708 #endif
709
710 #ifdef LDAP_DEBUG
711
712 static int
713 at_index_printnode( struct aindexrec *air )
714 {
715
716         printf( "%s = %s\n", air->air_name, ldap_attributetype2str(&air->air_at->sat_atype) );
717         return( 0 );
718 }
719
720 static void
721 at_index_print( void )
722 {
723         printf("Printing attribute type index:\n");
724         (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode,
725                 0, -1, AVL_INORDER );
726 }
727
728 #endif