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