]> git.sur5r.net Git - openldap/blob - servers/slapd/attr.c
(re)introduce o_connid such that STATS doesn't need c_mutex (which it
[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         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                 at->at_ordering_oid = "2.5.13.3";
231                 at->at_substr_oid = "2.5.13.4";
232         } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 ||
233             strcasecmp( argv[lasti], "tel" ) == 0 ) {
234                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.50";
235                 at->at_equality_oid = "2.5.13.20";
236                 at->at_substr_oid = "2.5.13.21";
237         } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) {
238                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.12";
239                 at->at_equality_oid = "2.5.13.1";
240         } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 ||
241             strcasecmp( argv[lasti], "ces" ) == 0 ) {
242                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15";
243                 at->at_equality_oid = "2.5.13.5";
244                 at->at_ordering_oid = "2.5.13.6";
245                 at->at_substr_oid = "2.5.13.7";
246         } else if ( strcasecmp( argv[lasti], "binary" ) == 0 ||
247             strcasecmp( argv[lasti], "bin" ) == 0 ) {
248                 at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.5";
249                 /* There is no match for binary syntax. Really */
250         } else {
251                 Debug( LDAP_DEBUG_ANY,
252             "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n",
253                     fname, lineno, argv[lasti] );
254                 Debug( LDAP_DEBUG_ANY,
255     "possible syntaxes are \"cis\", \"ces\", \"tel\", \"dn\", or \"bin\"\n",
256                     0, 0, 0 );
257                 free( (AttributeType *) at );
258                 return;
259         }
260
261         save = argv[lasti];
262         argv[lasti] = NULL;
263         at->at_names = charray_dup( argv );
264         argv[lasti] = save;
265
266         code = at_add( at, &err );
267         if ( code ) {
268                 fprintf( stderr, "%s: line %d: %s %s\n",
269                          fname, lineno, scherr2str(code), err);
270                 exit( 1 );
271         }
272         ldap_memfree(at);
273 }
274
275 int
276 at_fake_if_needed(
277     char        *name
278 )
279 {
280         char *argv[3];
281
282         if ( at_find( name ) ) {
283                 return 0;
284         } else {
285                 argv[0] = name;
286                 argv[1] = "cis";
287                 argv[2] = NULL;
288                 attr_syntax_config( "implicit", 0, 2, argv );
289                 return 0;
290         }
291 }
292
293 struct aindexrec {
294         char            *air_name;
295         AttributeType   *air_at;
296 };
297
298 static Avlnode  *attr_index = NULL;
299 static AttributeType *attr_list = NULL;
300
301 static int
302 attr_index_cmp(
303     struct aindexrec    *air1,
304     struct aindexrec    *air2
305 )
306 {
307         return (strcasecmp( air1->air_name, air2->air_name ));
308 }
309
310 static int
311 attr_index_name_cmp(
312     char                *type,
313     struct aindexrec    *air
314 )
315 {
316         return (strcasecmp( type, air->air_name ));
317 }
318
319 AttributeType *
320 at_find(
321     const char          *name
322 )
323 {
324         struct aindexrec        *air = NULL;
325
326         if ( (air = (struct aindexrec *) avl_find( attr_index, name,
327             (AVL_CMP) attr_index_name_cmp )) != NULL ) {
328                 return( air->air_at );
329         }
330         return( NULL );
331 }
332
333 int
334 at_append_to_list(
335     AttributeType       *sat,
336     AttributeType       ***listp
337 )
338 {
339         AttributeType   **list;
340         AttributeType   **list1;
341         int             size;
342
343         list = *listp;
344         if ( !list ) {
345                 size = 2;
346                 list = calloc(size, sizeof(AttributeType *));
347                 if ( !list ) {
348                         return -1;
349                 }
350         } else {
351                 size = 0;
352                 list1 = *listp;
353                 while ( *list1 ) {
354                         size++;
355                         list1++;
356                 }
357                 size += 2;
358                 list1 = realloc(list, size*sizeof(AttributeType *));
359                 if ( !list1 ) {
360                         return -1;
361                 }
362                 list = list1;
363         }
364         list[size-2] = sat;
365         list[size-1] = NULL;
366         *listp = list;
367         return 0;
368 }
369
370 int
371 at_delete_from_list(
372     int                 pos,
373     AttributeType       ***listp
374 )
375 {
376         AttributeType   **list;
377         AttributeType   **list1;
378         int             i;
379         int             j;
380
381         if ( pos < 0 ) {
382                 return -2;
383         }
384         list = *listp;
385         for ( i=0; list[i]; i++ )
386                 ;
387         if ( pos >= i ) {
388                 return -2;
389         }
390         for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
391                 list[i] = list[j];
392         }
393         list[i] = NULL;
394         /* Tell the runtime this can be shrinked */
395         list1 = realloc(list, (i+1)*sizeof(AttributeType **));
396         if ( !list1 ) {
397                 return -1;
398         }
399         *listp = list1;
400         return 0;
401 }
402
403 int
404 at_find_in_list(
405     AttributeType       *sat,
406     AttributeType       **list
407 )
408 {
409         int     i;
410
411         if ( !list ) {
412                 return -1;
413         }
414         for ( i=0; list[i]; i++ ) {
415                 if ( sat == list[i] ) {
416                         return i;
417                 }
418         }
419         return -1;
420 }
421
422 static int
423 at_insert(
424     AttributeType       *sat,
425     const char          **err
426 )
427 {
428         AttributeType           **atp;
429         struct aindexrec        *air;
430         char                    **names;
431
432         atp = &attr_list;
433         while ( *atp != NULL ) {
434                 atp = &(*atp)->sat_next;
435         }
436         *atp = sat;
437
438         if ( sat->sat_oid ) {
439                 air = (struct aindexrec *)
440                         ch_calloc( 1, sizeof(struct aindexrec) );
441                 air->air_name = sat->sat_oid;
442                 air->air_at = sat;
443                 if ( avl_insert( &attr_index, (caddr_t) air,
444                                  (AVL_CMP) attr_index_cmp,
445                                  (AVL_DUP) avl_dup_error ) ) {
446                         *err = sat->sat_oid;
447                         ldap_memfree(air);
448                         return SLAP_SCHERR_DUP_ATTR;
449                 }
450                 /* FIX: temporal consistency check */
451                 at_find(air->air_name);
452         }
453         if ( (names = sat->sat_names) ) {
454                 while ( *names ) {
455                         air = (struct aindexrec *)
456                                 ch_calloc( 1, sizeof(struct aindexrec) );
457                         air->air_name = ch_strdup(*names);
458                         air->air_at = sat;
459                         if ( avl_insert( &attr_index, (caddr_t) air,
460                                          (AVL_CMP) attr_index_cmp,
461                                          (AVL_DUP) avl_dup_error ) ) {
462                                 *err = *names;
463                                 ldap_memfree(air);
464                                 return SLAP_SCHERR_DUP_ATTR;
465                         }
466                         /* FIX: temporal consistency check */
467                         at_find(air->air_name);
468                         names++;
469                 }
470         }
471
472         return 0;
473 }
474
475 int
476 at_add(
477     LDAP_ATTRIBUTE_TYPE *at,
478     const char          **err
479 )
480 {
481         AttributeType   *sat;
482         AttributeType   *sat1;
483         MatchingRule    *mr;
484         Syntax          *syn;
485         int             code;
486         char            *errattr;
487
488         if ( at->at_names && at->at_names[0] ) {
489                 errattr = at->at_names[0];
490         } else if ( at->at_oid ) {
491                 errattr = at->at_oid;
492         } else {
493                 errattr = "";
494                 return SLAP_SCHERR_ATTR_INCOMPLETE;
495         }
496         sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
497         memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE));
498         if ( at->at_sup_oid ) {
499                 if ( (sat1 = at_find(at->at_sup_oid)) ) {
500                         sat->sat_sup = sat1;
501                         if ( at_append_to_list(sat, &sat1->sat_subtypes) ) {
502                                 *err = errattr;
503                                 return SLAP_SCHERR_OUTOFMEM;
504                         }
505                 } else {
506                         *err = at->at_sup_oid;
507                         return SLAP_SCHERR_ATTR_NOT_FOUND;
508                 }
509         }
510
511         if ( at->at_syntax_oid ) {
512                 if ( (syn = syn_find(sat->sat_syntax_oid)) ) {
513                         sat->sat_syntax = syn;
514                 } else {
515                         *err = sat->sat_syntax_oid;
516                         return SLAP_SCHERR_SYN_NOT_FOUND;
517                 }
518                 if ( !strcmp(at->at_syntax_oid,
519                              "1.3.6.1.4.1.1466.115.121.1.15") ) {
520                         if ( at->at_equality_oid &&
521                              !strcmp(at->at_equality_oid, "2.5.13.5") ) {
522                                 sat->sat_syntax_compat = SYNTAX_CES;
523                         } else {
524                                 sat->sat_syntax_compat = SYNTAX_CIS;
525                         }
526                 } else if ( !strcmp(at->at_syntax_oid,
527                                     "1.3.6.1.4.1.1466.115.121.1.50") ) {
528                         sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL;
529                 } else if ( !strcmp(at->at_syntax_oid,
530                                     "1.3.6.1.4.1.1466.115.121.1.12") ) {
531                         sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN;
532                 } else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) {
533                         sat->sat_syntax_compat = SYNTAX_BIN;
534                 } else {
535                         sat->sat_syntax_compat = DEFAULT_SYNTAX;
536                 }
537         } else {
538                 sat->sat_syntax_compat = DEFAULT_SYNTAX;
539         }
540
541         if ( sat->sat_equality_oid ) {
542                 if ( (mr = mr_find(sat->sat_equality_oid)) ) {
543                         sat->sat_equality = mr;
544                 } else {
545                         *err = sat->sat_equality_oid;
546                         return SLAP_SCHERR_MR_NOT_FOUND;
547                 }
548         }
549         if ( sat->sat_ordering_oid ) {
550                 if ( (mr = mr_find(sat->sat_ordering_oid)) ) {
551                         sat->sat_ordering = mr;
552                 } else {
553                         *err = sat->sat_ordering_oid;
554                         return SLAP_SCHERR_MR_NOT_FOUND;
555                 }
556         }
557         if ( sat->sat_substr_oid ) {
558                 if ( (mr = mr_find(sat->sat_substr_oid)) ) {
559                         sat->sat_substr = mr;
560                 } else {
561                         *err = sat->sat_substr_oid;
562                         return SLAP_SCHERR_MR_NOT_FOUND;
563                 }
564         }
565
566         /*
567          * Now inherit definitions from superiors.  We only check the
568          * direct superior since that one has already inherited from
569          * its own superiorss
570          */
571         if ( sat->sat_sup ) {
572                 if ( !sat->sat_syntax ) {
573                         sat->sat_syntax = sat->sat_sup->sat_syntax;
574                         sat->sat_syntax_len = sat->sat_sup->sat_syntax_len;
575                 }
576                 if ( !sat->sat_equality ) {
577                         sat->sat_equality = sat->sat_sup->sat_equality;
578                 }
579                 if ( !sat->sat_ordering ) {
580                         sat->sat_ordering = sat->sat_sup->sat_ordering;
581                 }
582                 if ( !sat->sat_substr ) {
583                         sat->sat_substr = sat->sat_sup->sat_substr;
584                 }
585         }
586         code = at_insert(sat,err);
587         return code;
588 }
589
590
591 char *
592 at_canonical_name( char * a_type )
593 {
594         AttributeType   *atp;
595
596         if ( (atp=at_find(a_type)) == NULL ) {
597
598                 return a_type;
599
600         } else  if ( atp->sat_names 
601                      && atp->sat_names[0]
602                      && (*(atp->sat_names[0]) != '\0') ) {
603             
604                 return atp->sat_names[0];
605
606         } else if (atp->sat_oid && (*atp->sat_oid != '\0')) {
607
608                 return atp->sat_oid;
609                 
610         } else {
611
612                 return a_type;
613
614         }
615
616 }/* char * at_canonica_name() */
617
618
619 #if defined( SLAPD_SCHEMA_DN )
620
621 int
622 at_schema_info( Entry *e )
623 {
624         struct berval   val;
625         struct berval   *vals[2];
626         AttributeType   *at;
627
628         vals[0] = &val;
629         vals[1] = NULL;
630
631         for ( at = attr_list; at; at = at->sat_next ) {
632                 val.bv_val = ldap_attributetype2str( &at->sat_atype );
633                 if ( val.bv_val ) {
634                         val.bv_len = strlen( val.bv_val );
635                         Debug( LDAP_DEBUG_TRACE, "Merging at [%d] %s\n",
636                                val.bv_len, val.bv_val, 0 );
637                         attr_merge( e, "attributeTypes", vals );
638                         ldap_memfree( val.bv_val );
639                 } else {
640                         return -1;
641                 }
642         }
643         return 0;
644 }
645 #endif
646
647 #ifdef LDAP_DEBUG
648
649 static int
650 at_index_printnode( struct aindexrec *air )
651 {
652
653         printf( "%s = %s\n", air->air_name, ldap_attributetype2str(&air->air_at->sat_atype) );
654         return( 0 );
655 }
656
657 static void
658 at_index_print( void )
659 {
660         printf("Printing attribute type index:\n");
661         (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode,
662                 0, -1, AVL_INORDER );
663 }
664
665 #endif