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