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