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