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