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