1 /*        $NetBSD: at.c,v 1.3 2021/08/14 16:14:58 christos Exp $      */
2 
3 /* at.c - routines for dealing with attribute types */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 #include <sys/cdefs.h>
20 __RCSID("$NetBSD: at.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 
26 #include <ac/ctype.h>
27 #include <ac/errno.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31 
32 #include "slap.h"
33 
34 
35 const char *
at_syntax(AttributeType * at)36 at_syntax(
37           AttributeType       *at )
38 {
39           for ( ; at != NULL; at = at->sat_sup ) {
40                     if ( at->sat_syntax_oid ) {
41                               return at->sat_syntax_oid;
42                     }
43           }
44 
45           assert( 0 );
46 
47           return NULL;
48 }
49 
50 int
is_at_syntax(AttributeType * at,const char * oid)51 is_at_syntax(
52           AttributeType       *at,
53           const char          *oid )
54 {
55           const char *syn_oid = at_syntax( at );
56 
57           if ( syn_oid ) {
58                     return strcmp( syn_oid, oid ) == 0;
59           }
60 
61           return 0;
62 }
63 
is_at_subtype(AttributeType * sub,AttributeType * sup)64 int is_at_subtype(
65           AttributeType *sub,
66           AttributeType *sup )
67 {
68           for( ; sub != NULL; sub = sub->sat_sup ) {
69                     if( sub == sup ) return 1;
70           }
71 
72           return 0;
73 }
74 
75 struct aindexrec {
76           struct berval       air_name;
77           AttributeType       *air_at;
78 };
79 
80 static Avlnode      *attr_index = NULL;
81 static Avlnode      *attr_cache = NULL;
82 static LDAP_STAILQ_HEAD(ATList, AttributeType) attr_list
83           = LDAP_STAILQ_HEAD_INITIALIZER(attr_list);
84 
85 /* Last hardcoded attribute registered */
86 AttributeType *at_sys_tail;
87 
88 int at_oc_cache;
89 
90 static int
attr_index_cmp(const void * v_air1,const void * v_air2)91 attr_index_cmp(
92     const void      *v_air1,
93     const void      *v_air2 )
94 {
95           const struct aindexrec        *air1 = v_air1;
96           const struct aindexrec        *air2 = v_air2;
97           int i = air1->air_name.bv_len - air2->air_name.bv_len;
98           if (i) return i;
99           return (strcasecmp( air1->air_name.bv_val, air2->air_name.bv_val ));
100 }
101 
102 static int
attr_index_name_cmp(const void * v_type,const void * v_air)103 attr_index_name_cmp(
104     const void      *v_type,
105     const void      *v_air )
106 {
107     const struct berval    *type = v_type;
108     const struct aindexrec *air  = v_air;
109           int i = type->bv_len - air->air_name.bv_len;
110           if (i) return i;
111           return (strncasecmp( type->bv_val, air->air_name.bv_val, type->bv_len ));
112 }
113 
114 AttributeType *
at_find(const char * name)115 at_find( const char *name )
116 {
117           struct berval bv;
118 
119           bv.bv_val = (char *)name;
120           bv.bv_len = strlen( name );
121 
122           return at_bvfind( &bv );
123 }
124 
125 AttributeType *
at_bvfind(struct berval * name)126 at_bvfind( struct berval *name )
127 {
128           struct aindexrec *air;
129 
130           if ( attr_cache ) {
131                     air = ldap_avl_find( attr_cache, name, attr_index_name_cmp );
132                     if ( air ) return air->air_at;
133           }
134 
135           air = ldap_avl_find( attr_index, name, attr_index_name_cmp );
136 
137           if ( air ) {
138                     if ( air->air_at->sat_flags & SLAP_AT_DELETED ) {
139                               air = NULL;
140                     } else if (( slapMode & SLAP_TOOL_MODE ) && at_oc_cache ) {
141                               ldap_avl_insert( &attr_cache, (caddr_t) air,
142                                         attr_index_cmp, ldap_avl_dup_error );
143                     }
144           }
145 
146           return air != NULL ? air->air_at : NULL;
147 }
148 
149 int
at_append_to_list(AttributeType * sat,AttributeType *** listp)150 at_append_to_list(
151     AttributeType   *sat,
152     AttributeType   ***listp )
153 {
154           AttributeType       **list;
155           AttributeType       **list1;
156           int                 size;
157 
158           list = *listp;
159           if ( !list ) {
160                     size = 2;
161                     list = ch_calloc(size, sizeof(AttributeType *));
162                     if ( !list ) {
163                               return -1;
164                     }
165           } else {
166                     size = 0;
167                     list1 = *listp;
168                     while ( *list1 ) {
169                               size++;
170                               list1++;
171                     }
172                     size += 2;
173                     list1 = ch_realloc(list, size*sizeof(AttributeType *));
174                     if ( !list1 ) {
175                               return -1;
176                     }
177                     list = list1;
178           }
179           list[size-2] = sat;
180           list[size-1] = NULL;
181           *listp = list;
182           return 0;
183 }
184 
185 int
at_delete_from_list(int pos,AttributeType *** listp)186 at_delete_from_list(
187     int                       pos,
188     AttributeType   ***listp )
189 {
190           AttributeType       **list;
191           AttributeType       **list1;
192           int                 i;
193           int                 j;
194 
195           if ( pos < 0 ) {
196                     return -2;
197           }
198           list = *listp;
199           for ( i=0; list[i]; i++ )
200                     ;
201           if ( pos >= i ) {
202                     return -2;
203           }
204           for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
205                     list[i] = list[j];
206           }
207           list[i] = NULL;
208           /* Tell the runtime this can be shrunk */
209           list1 = ch_realloc(list, (i+1)*sizeof(AttributeType **));
210           if ( !list1 ) {
211                     return -1;
212           }
213           *listp = list1;
214           return 0;
215 }
216 
217 int
at_find_in_list(AttributeType * sat,AttributeType ** list)218 at_find_in_list(
219     AttributeType   *sat,
220     AttributeType   **list )
221 {
222           int       i;
223 
224           if ( !list ) {
225                     return -1;
226           }
227           for ( i=0; list[i]; i++ ) {
228                     if ( sat == list[i] ) {
229                               return i;
230                     }
231           }
232           return -1;
233 }
234 
235 static void
at_delete_names(AttributeType * at)236 at_delete_names( AttributeType *at )
237 {
238           char                          **names = at->sat_names;
239 
240           if (!names) return;
241 
242           while (*names) {
243                     struct aindexrec    tmpair, *air;
244 
245                     ber_str2bv( *names, 0, 0, &tmpair.air_name );
246                     tmpair.air_at = at;
247                     air = (struct aindexrec *)ldap_avl_delete( &attr_index,
248                               (caddr_t)&tmpair, attr_index_cmp );
249                     assert( air != NULL );
250                     ldap_memfree( air );
251                     names++;
252           }
253 }
254 
255 /* Mark the attribute as deleted, remove from list, and remove all its
256  * names from the AVL tree. Leave the OID in the tree.
257  */
258 void
at_delete(AttributeType * at)259 at_delete( AttributeType *at )
260 {
261           at->sat_flags |= SLAP_AT_DELETED;
262 
263           LDAP_STAILQ_REMOVE(&attr_list, at, AttributeType, sat_next);
264 
265           at_delete_names( at );
266 }
267 
268 static void
at_clean(AttributeType * a)269 at_clean( AttributeType *a )
270 {
271           if ( a->sat_equality ) {
272                     MatchingRule        *mr;
273 
274                     mr = mr_find( a->sat_equality->smr_oid );
275                     assert( mr != NULL );
276                     if ( mr != a->sat_equality ) {
277                               ch_free( a->sat_equality );
278                               a->sat_equality = NULL;
279                     }
280           }
281 
282           assert( a->sat_syntax != NULL );
283           if ( a->sat_syntax != NULL ) {
284                     Syntax              *syn;
285 
286                     syn = syn_find( a->sat_syntax->ssyn_oid );
287                     assert( syn != NULL );
288                     if ( syn != a->sat_syntax ) {
289                               ch_free( a->sat_syntax );
290                               a->sat_syntax = NULL;
291                     }
292           }
293 
294           if ( a->sat_oidmacro ) {
295                     ldap_memfree( a->sat_oidmacro );
296                     a->sat_oidmacro = NULL;
297           }
298           if ( a->sat_soidmacro ) {
299                     ldap_memfree( a->sat_soidmacro );
300                     a->sat_soidmacro = NULL;
301           }
302           if ( a->sat_subtypes ) {
303                     ldap_memfree( a->sat_subtypes );
304                     a->sat_subtypes = NULL;
305           }
306 }
307 
308 static void
at_destroy_one(void * v)309 at_destroy_one( void *v )
310 {
311           struct aindexrec *air = v;
312           AttributeType *a = air->air_at;
313 
314           at_clean( a );
315           ad_destroy(a->sat_ad);
316           ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex);
317           ldap_attributetype_free((LDAPAttributeType *)a);
318           ldap_memfree(air);
319 }
320 
321 void
at_destroy(void)322 at_destroy( void )
323 {
324           AttributeType *a;
325 
326           while( !LDAP_STAILQ_EMPTY(&attr_list) ) {
327                     a = LDAP_STAILQ_FIRST(&attr_list);
328                     LDAP_STAILQ_REMOVE_HEAD(&attr_list, sat_next);
329 
330                     at_delete_names( a );
331           }
332 
333           ldap_avl_free(attr_index, at_destroy_one);
334 
335           if ( slap_schema.si_at_undefined ) {
336                     ad_destroy(slap_schema.si_at_undefined->sat_ad);
337           }
338 
339           if ( slap_schema.si_at_proxied ) {
340                     ad_destroy(slap_schema.si_at_proxied->sat_ad);
341           }
342 }
343 
344 int
at_start(AttributeType ** at)345 at_start( AttributeType **at )
346 {
347           assert( at != NULL );
348 
349           *at = LDAP_STAILQ_FIRST(&attr_list);
350 
351           return (*at != NULL);
352 }
353 
354 int
at_next(AttributeType ** at)355 at_next( AttributeType **at )
356 {
357           assert( at != NULL );
358 
359 #if 0     /* pedantic check: don't use this */
360           {
361                     AttributeType *tmp = NULL;
362 
363                     LDAP_STAILQ_FOREACH(tmp,&attr_list,sat_next) {
364                               if ( tmp == *at ) {
365                                         break;
366                               }
367                     }
368 
369                     assert( tmp != NULL );
370           }
371 #endif
372 
373           if ( *at == NULL ) {
374                     return 0;
375           }
376 
377           *at = LDAP_STAILQ_NEXT(*at,sat_next);
378 
379           return (*at != NULL);
380 }
381 
382 /*
383  * check whether the two attributeTypes actually __are__ identical,
384  * or rather inconsistent
385  */
386 static int
at_check_dup(AttributeType * sat,AttributeType * new_sat)387 at_check_dup(
388           AttributeType                 *sat,
389           AttributeType                 *new_sat )
390 {
391           if ( new_sat->sat_oid != NULL ) {
392                     if ( sat->sat_oid == NULL ) {
393                               return SLAP_SCHERR_ATTR_INCONSISTENT;
394                     }
395 
396                     if ( strcmp( sat->sat_oid, new_sat->sat_oid ) != 0 ) {
397                               return SLAP_SCHERR_ATTR_INCONSISTENT;
398                     }
399 
400           } else {
401                     if ( sat->sat_oid != NULL ) {
402                               return SLAP_SCHERR_ATTR_INCONSISTENT;
403                     }
404           }
405 
406           if ( new_sat->sat_names ) {
407                     int       i;
408 
409                     if ( sat->sat_names == NULL ) {
410                               return SLAP_SCHERR_ATTR_INCONSISTENT;
411                     }
412 
413                     for ( i = 0; new_sat->sat_names[ i ]; i++ ) {
414                               if ( sat->sat_names[ i ] == NULL ) {
415                                         return SLAP_SCHERR_ATTR_INCONSISTENT;
416                               }
417 
418                               if ( strcasecmp( sat->sat_names[ i ],
419                                                   new_sat->sat_names[ i ] ) != 0 )
420                               {
421                                         return SLAP_SCHERR_ATTR_INCONSISTENT;
422                               }
423                     }
424           } else {
425                     if ( sat->sat_names != NULL ) {
426                               return SLAP_SCHERR_ATTR_INCONSISTENT;
427                     }
428           }
429 
430           return SLAP_SCHERR_ATTR_DUP;
431 }
432 
433 static struct aindexrec *air_old;
434 
435 static int
at_dup_error(void * left,void * right)436 at_dup_error( void *left, void *right )
437 {
438           air_old = left;
439           return -1;
440 }
441 
442 static int
at_insert(AttributeType ** rat,AttributeType * prev,const char ** err)443 at_insert(
444     AttributeType   **rat,
445           AttributeType       *prev,
446     const char                **err )
447 {
448           struct aindexrec    *air;
449           char                          **names = NULL;
450           AttributeType       *sat = *rat;
451 
452           if ( sat->sat_oid ) {
453                     air = (struct aindexrec *)
454                               ch_calloc( 1, sizeof(struct aindexrec) );
455                     ber_str2bv( sat->sat_oid, 0, 0, &air->air_name );
456                     air->air_at = sat;
457                     air_old = NULL;
458 
459                     if ( ldap_avl_insert( &attr_index, (caddr_t) air,
460                                      attr_index_cmp, at_dup_error ) )
461                     {
462                               AttributeType       *old_sat;
463                               int                 rc;
464 
465                               *err = sat->sat_oid;
466 
467                               assert( air_old != NULL );
468                               old_sat = air_old->air_at;
469 
470                               /* replacing a deleted definition? */
471                               if ( old_sat->sat_flags & SLAP_AT_DELETED ) {
472                                         AttributeType tmp;
473                                         AttributeDescription *ad;
474 
475                                         /* Keep old oid, free new oid;
476                                          * Keep old ads, free new ads;
477                                          * Keep old ad_mutex, free new ad_mutex;
478                                          * Keep new everything else, free old
479                                          */
480                                         tmp = *old_sat;
481                                         *old_sat = *sat;
482                                         old_sat->sat_oid = tmp.sat_oid;
483                                         tmp.sat_oid = sat->sat_oid;
484                                         old_sat->sat_ad = tmp.sat_ad;
485                                         tmp.sat_ad = sat->sat_ad;
486                                         old_sat->sat_ad_mutex = tmp.sat_ad_mutex;
487                                         tmp.sat_ad_mutex = sat->sat_ad_mutex;
488                                         *sat = tmp;
489 
490                                         /* Check for basic ad pointing at old cname */
491                                         for ( ad = old_sat->sat_ad; ad; ad=ad->ad_next ) {
492                                                   if ( ad->ad_cname.bv_val == sat->sat_cname.bv_val ) {
493                                                             ad->ad_cname = old_sat->sat_cname;
494                                                             break;
495                                                   }
496                                         }
497 
498                                         at_clean( sat );
499                                         at_destroy_one( air );
500 
501                                         air = air_old;
502                                         sat = old_sat;
503                                         *rat = sat;
504                               } else {
505                                         ldap_memfree( air );
506 
507                                         rc = at_check_dup( old_sat, sat );
508 
509                                         return rc;
510                               }
511                     }
512                     /* FIX: temporal consistency check */
513                     at_bvfind( &air->air_name );
514           }
515 
516           names = sat->sat_names;
517           if ( names ) {
518                     while ( *names ) {
519                               air = (struct aindexrec *)
520                                         ch_calloc( 1, sizeof(struct aindexrec) );
521                               ber_str2bv( *names, 0, 0, &air->air_name );
522                               air->air_at = sat;
523                               if ( ldap_avl_insert( &attr_index, (caddr_t) air,
524                                                attr_index_cmp, ldap_avl_dup_error ) )
525                               {
526                                         AttributeType       *old_sat;
527                                         int                 rc;
528 
529                                         *err = *names;
530 
531                                         old_sat = at_bvfind( &air->air_name );
532                                         assert( old_sat != NULL );
533                                         rc = at_check_dup( old_sat, sat );
534 
535                                         ldap_memfree(air);
536 
537                                         while ( names > sat->sat_names ) {
538                                                   struct aindexrec    tmpair;
539 
540                                                   names--;
541                                                   ber_str2bv( *names, 0, 0, &tmpair.air_name );
542                                                   tmpair.air_at = sat;
543                                                   air = (struct aindexrec *)ldap_avl_delete( &attr_index,
544                                                             (caddr_t)&tmpair, attr_index_cmp );
545                                                   assert( air != NULL );
546                                                   ldap_memfree( air );
547                                         }
548 
549                                         if ( sat->sat_oid ) {
550                                                   struct aindexrec    tmpair;
551 
552                                                   ber_str2bv( sat->sat_oid, 0, 0, &tmpair.air_name );
553                                                   tmpair.air_at = sat;
554                                                   air = (struct aindexrec *)ldap_avl_delete( &attr_index,
555                                                             (caddr_t)&tmpair, attr_index_cmp );
556                                                   assert( air != NULL );
557                                                   ldap_memfree( air );
558                                         }
559 
560                                         return rc;
561                               }
562                               /* FIX: temporal consistency check */
563                               at_bvfind(&air->air_name);
564                               names++;
565                     }
566           }
567 
568           if ( sat->sat_oid ) {
569                     slap_ad_undef_promote( sat->sat_oid, sat );
570           }
571 
572           names = sat->sat_names;
573           if ( names ) {
574                     while ( *names ) {
575                               slap_ad_undef_promote( *names, sat );
576                               names++;
577                     }
578           }
579 
580           if ( sat->sat_flags & SLAP_AT_HARDCODE ) {
581                     prev = at_sys_tail;
582                     at_sys_tail = sat;
583           }
584           if ( prev ) {
585                     LDAP_STAILQ_INSERT_AFTER( &attr_list, prev, sat, sat_next );
586           } else {
587                     LDAP_STAILQ_INSERT_TAIL( &attr_list, sat, sat_next );
588           }
589 
590           return 0;
591 }
592 
593 int
at_add(LDAPAttributeType * at,int user,AttributeType ** rsat,AttributeType * prev,const char ** err)594 at_add(
595           LDAPAttributeType   *at,
596           int                           user,
597           AttributeType                 **rsat,
598           AttributeType       *prev,
599           const char                    **err )
600 {
601           AttributeType       *sat = NULL;
602           MatchingRule        *mr = NULL;
603           Syntax              *syn = NULL;
604           int                 i;
605           int                 code = LDAP_SUCCESS;
606           char                *cname = NULL;
607           char                *oidm = NULL;
608           char                *soidm = NULL;
609 
610           if ( !at->at_oid ) {
611                     *err = "";
612                     return SLAP_SCHERR_ATTR_INCOMPLETE;
613           }
614 
615           if ( !OID_LEADCHAR( at->at_oid[0] )) {
616                     char      *oid;
617 
618                     /* Expand OID macros */
619                     oid = oidm_find( at->at_oid );
620                     if ( !oid ) {
621                               *err = at->at_oid;
622                               return SLAP_SCHERR_OIDM;
623                     }
624                     if ( oid != at->at_oid ) {
625                               oidm = at->at_oid;
626                               at->at_oid = oid;
627                     }
628           }
629 
630           if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
631                     char      *oid;
632 
633                     /* Expand OID macros */
634                     oid = oidm_find( at->at_syntax_oid );
635                     if ( !oid ) {
636                               *err = at->at_syntax_oid;
637                               code = SLAP_SCHERR_OIDM;
638                               goto error_return;
639                     }
640                     if ( oid != at->at_syntax_oid ) {
641                               soidm = at->at_syntax_oid;
642                               at->at_syntax_oid = oid;
643                     }
644           }
645 
646           if ( at->at_names && at->at_names[0] ) {
647                     int i;
648 
649                     for( i=0; at->at_names[i]; i++ ) {
650                               if( !slap_valid_descr( at->at_names[i] ) ) {
651                                         *err = at->at_names[i];
652                                         code = SLAP_SCHERR_BAD_DESCR;
653                                         goto error_return;
654                               }
655                     }
656 
657                     cname = at->at_names[0];
658 
659           } else {
660                     cname = at->at_oid;
661 
662           }
663 
664           *err = cname;
665 
666           if ( !at->at_usage && at->at_no_user_mod ) {
667                     /* user attribute must be modifiable */
668                     code = SLAP_SCHERR_ATTR_BAD_USAGE;
669                     goto error_return;
670           }
671 
672           if ( at->at_collective ) {
673                     if( at->at_usage ) {
674                               /* collective attributes cannot be operational */
675                               code = SLAP_SCHERR_ATTR_BAD_USAGE;
676                               goto error_return;
677                     }
678 
679                     if( at->at_single_value ) {
680                               /* collective attributes cannot be single-valued */
681                               code = SLAP_SCHERR_ATTR_BAD_USAGE;
682                               goto error_return;
683                     }
684           }
685 
686           sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
687           AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType));
688 
689           sat->sat_cname.bv_val = cname;
690           sat->sat_cname.bv_len = strlen( cname );
691           sat->sat_oidmacro = oidm;
692           sat->sat_soidmacro = soidm;
693           ldap_pvt_thread_mutex_init(&sat->sat_ad_mutex);
694 
695           if ( at->at_sup_oid ) {
696                     AttributeType *supsat = at_find(at->at_sup_oid);
697 
698                     if ( supsat == NULL ) {
699                               *err = at->at_sup_oid;
700                               code = SLAP_SCHERR_ATTR_NOT_FOUND;
701                               goto error_return;
702                     }
703 
704                     sat->sat_sup = supsat;
705 
706                     if ( at_append_to_list(sat, &supsat->sat_subtypes) ) {
707                               code = SLAP_SCHERR_OUTOFMEM;
708                               goto error_return;
709                     }
710 
711                     if ( sat->sat_usage != supsat->sat_usage ) {
712                               /* subtypes must have same usage as their SUP */
713                               code = SLAP_SCHERR_ATTR_BAD_USAGE;
714                               goto error_return;
715                     }
716 
717                     if ( supsat->sat_obsolete && !sat->sat_obsolete ) {
718                               /* subtypes must be obsolete if super is */
719                               code = SLAP_SCHERR_ATTR_BAD_SUP;
720                               goto error_return;
721                     }
722 
723                     if ( sat->sat_flags & SLAP_AT_FINAL ) {
724                               /* cannot subtype a "final" attribute type */
725                               code = SLAP_SCHERR_ATTR_BAD_SUP;
726                               goto error_return;
727                     }
728           }
729 
730           /*
731            * Inherit definitions from superiors.  We only check the
732            * direct superior since that one has already inherited from
733            * its own superiors
734            */
735           if ( sat->sat_sup ) {
736                     Syntax *syn = syn_find(sat->sat_sup->sat_syntax->ssyn_oid);
737                     if ( syn != sat->sat_sup->sat_syntax ) {
738                               sat->sat_syntax = ch_malloc( sizeof( Syntax ));
739                               *sat->sat_syntax = *sat->sat_sup->sat_syntax;
740                     } else {
741                               sat->sat_syntax = sat->sat_sup->sat_syntax;
742                     }
743                     if ( sat->sat_sup->sat_equality ) {
744                               MatchingRule *mr = mr_find( sat->sat_sup->sat_equality->smr_oid );
745                               if ( mr != sat->sat_sup->sat_equality ) {
746                                         sat->sat_equality = ch_malloc( sizeof( MatchingRule ));
747                                         *sat->sat_equality = *sat->sat_sup->sat_equality;
748                               } else {
749                                         sat->sat_equality = sat->sat_sup->sat_equality;
750                               }
751                     }
752                     sat->sat_approx = sat->sat_sup->sat_approx;
753                     sat->sat_ordering = sat->sat_sup->sat_ordering;
754                     sat->sat_substr = sat->sat_sup->sat_substr;
755           }
756 
757           /*
758            * check for X-ORDERED attributes
759            */
760           if ( sat->sat_extensions ) {
761                     for (i=0; sat->sat_extensions[i]; i++) {
762                               if (!strcasecmp( sat->sat_extensions[i]->lsei_name,
763                                         "X-ORDERED" ) && sat->sat_extensions[i]->lsei_values ) {
764                                         if ( !strcasecmp( sat->sat_extensions[i]->lsei_values[0],
765                                                   "VALUES" )) {
766                                                   sat->sat_flags |= SLAP_AT_ORDERED_VAL;
767                                                   break;
768                                         } else if ( !strcasecmp( sat->sat_extensions[i]->lsei_values[0],
769                                                   "SIBLINGS" )) {
770                                                   sat->sat_flags |= SLAP_AT_ORDERED_SIB;
771                                                   break;
772                                         }
773                               }
774                     }
775           }
776 
777           if ( !user )
778                     sat->sat_flags |= SLAP_AT_HARDCODE;
779 
780           if ( at->at_syntax_oid ) {
781                     syn = syn_find(sat->sat_syntax_oid);
782                     if ( syn == NULL ) {
783                               *err = sat->sat_syntax_oid;
784                               code = SLAP_SCHERR_SYN_NOT_FOUND;
785                               goto error_return;
786                     }
787 
788                     if ( sat->sat_syntax != NULL && sat->sat_syntax != syn ) {
789                               /* BEWARE: no loop detection! */
790                               if ( syn_is_sup( sat->sat_syntax, syn ) ) {
791                                         code = SLAP_SCHERR_ATTR_BAD_SUP;
792                                         goto error_return;
793                               }
794                     }
795 
796                     sat->sat_syntax = syn;
797 
798           } else if ( sat->sat_syntax == NULL ) {
799                     code = SLAP_SCHERR_ATTR_INCOMPLETE;
800                     goto error_return;
801           }
802 
803           if ( sat->sat_equality_oid ) {
804                     mr = mr_find(sat->sat_equality_oid);
805 
806                     if( mr == NULL ) {
807                               *err = sat->sat_equality_oid;
808                               code = SLAP_SCHERR_MR_NOT_FOUND;
809                               goto error_return;
810                     }
811 
812                     if(( mr->smr_usage & SLAP_MR_EQUALITY ) != SLAP_MR_EQUALITY ) {
813                               *err = sat->sat_equality_oid;
814                               code = SLAP_SCHERR_ATTR_BAD_MR;
815                               goto error_return;
816                     }
817 
818                     if( sat->sat_syntax != mr->smr_syntax ) {
819                               if( mr->smr_compat_syntaxes == NULL ) {
820                                         *err = sat->sat_equality_oid;
821                                         code = SLAP_SCHERR_ATTR_BAD_MR;
822                                         goto error_return;
823                               }
824 
825                               for(i=0; mr->smr_compat_syntaxes[i]; i++) {
826                                         if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) {
827                                                   i = -1;
828                                                   break;
829                                         }
830                               }
831 
832                               if( i >= 0 ) {
833                                         *err = sat->sat_equality_oid;
834                                         code = SLAP_SCHERR_ATTR_BAD_MR;
835                                         goto error_return;
836                               }
837                     }
838 
839                     sat->sat_equality = mr;
840                     sat->sat_approx = mr->smr_associated;
841           }
842 
843           if ( sat->sat_ordering_oid ) {
844                     if( !sat->sat_equality ) {
845                               *err = sat->sat_ordering_oid;
846                               code = SLAP_SCHERR_ATTR_BAD_MR;
847                               goto error_return;
848                     }
849 
850                     mr = mr_find(sat->sat_ordering_oid);
851 
852                     if( mr == NULL ) {
853                               *err = sat->sat_ordering_oid;
854                               code = SLAP_SCHERR_MR_NOT_FOUND;
855                               goto error_return;
856                     }
857 
858                     if(( mr->smr_usage & SLAP_MR_ORDERING ) != SLAP_MR_ORDERING ) {
859                               *err = sat->sat_ordering_oid;
860                               code = SLAP_SCHERR_ATTR_BAD_MR;
861                               goto error_return;
862                     }
863 
864                     if( sat->sat_syntax != mr->smr_syntax ) {
865                               if( mr->smr_compat_syntaxes == NULL ) {
866                                         *err = sat->sat_ordering_oid;
867                                         code = SLAP_SCHERR_ATTR_BAD_MR;
868                                         goto error_return;
869                               }
870 
871                               for(i=0; mr->smr_compat_syntaxes[i]; i++) {
872                                         if( sat->sat_syntax == mr->smr_compat_syntaxes[i] ) {
873                                                   i = -1;
874                                                   break;
875                                         }
876                               }
877 
878                               if( i >= 0 ) {
879                                         *err = sat->sat_ordering_oid;
880                                         code = SLAP_SCHERR_ATTR_BAD_MR;
881                                         goto error_return;
882                               }
883                     }
884 
885                     sat->sat_ordering = mr;
886           }
887 
888           if ( sat->sat_substr_oid ) {
889                     if( !sat->sat_equality ) {
890                               *err = sat->sat_substr_oid;
891                               code = SLAP_SCHERR_ATTR_BAD_MR;
892                               goto error_return;
893                     }
894 
895                     mr = mr_find(sat->sat_substr_oid);
896 
897                     if( mr == NULL ) {
898                               *err = sat->sat_substr_oid;
899                               code = SLAP_SCHERR_MR_NOT_FOUND;
900                               goto error_return;
901                     }
902 
903                     if(( mr->smr_usage & SLAP_MR_SUBSTR ) != SLAP_MR_SUBSTR ) {
904                               *err = sat->sat_substr_oid;
905                               code = SLAP_SCHERR_ATTR_BAD_MR;
906                               goto error_return;
907                     }
908 
909                     /* due to funky LDAP builtin substring rules,
910                      * we check against the equality rule assertion
911                      * syntax and compat syntaxes instead of those
912                      * associated with the substrings rule.
913                      */
914                     if( sat->sat_syntax != sat->sat_equality->smr_syntax ) {
915                               if( sat->sat_equality->smr_compat_syntaxes == NULL ) {
916                                         *err = sat->sat_substr_oid;
917                                         code = SLAP_SCHERR_ATTR_BAD_MR;
918                                         goto error_return;
919                               }
920 
921                               for(i=0; sat->sat_equality->smr_compat_syntaxes[i]; i++) {
922                                         if( sat->sat_syntax ==
923                                                   sat->sat_equality->smr_compat_syntaxes[i] )
924                                         {
925                                                   i = -1;
926                                                   break;
927                                         }
928                               }
929 
930                               if( i >= 0 ) {
931                                         *err = sat->sat_substr_oid;
932                                         code = SLAP_SCHERR_ATTR_BAD_MR;
933                                         goto error_return;
934                               }
935                     }
936 
937                     sat->sat_substr = mr;
938           }
939 
940           code = at_insert( &sat, prev, err );
941           if ( code != 0 ) {
942 error_return:;
943                     if ( sat ) {
944                               ldap_pvt_thread_mutex_destroy( &sat->sat_ad_mutex );
945                               ch_free( sat );
946                     }
947 
948                     if ( oidm ) {
949                               SLAP_FREE( at->at_oid );
950                               at->at_oid = oidm;
951                     }
952 
953                     if ( soidm ) {
954                               SLAP_FREE( at->at_syntax_oid );
955                               at->at_syntax_oid = soidm;
956                     }
957 
958           } else if ( rsat ) {
959                     *rsat = sat;
960           }
961 
962           return code;
963 }
964 
965 #ifdef LDAP_DEBUG
966 #ifdef SLAPD_UNUSED
967 static int
at_index_printnode(void * v_air,void * ignore)968 at_index_printnode( void *v_air, void *ignore )
969 {
970           struct aindexrec *air = v_air;
971           printf("%s = %s\n",
972                     air->air_name.bv_val,
973                     ldap_attributetype2str(&air->air_at->sat_atype) );
974           return( 0 );
975 }
976 
977 static void
at_index_print(void)978 at_index_print( void )
979 {
980           printf("Printing attribute type index:\n");
981           (void) ldap_avl_apply( attr_index, at_index_printnode, 0, -1, AVL_INORDER );
982 }
983 #endif
984 #endif
985 
986 void
at_unparse(BerVarray * res,AttributeType * start,AttributeType * end,int sys)987 at_unparse( BerVarray *res, AttributeType *start, AttributeType *end, int sys )
988 {
989           AttributeType *at;
990           int i, num;
991           struct berval bv, *bva = NULL, idx;
992           char ibuf[32];
993 
994           if ( !start )
995                     start = LDAP_STAILQ_FIRST( &attr_list );
996 
997           /* count the result size */
998           i = 0;
999           for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) {
1000                     if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break;
1001                     i++;
1002                     if ( at == end ) break;
1003           }
1004           if (!i) return;
1005 
1006           num = i;
1007           bva = ch_malloc( (num+1) * sizeof(struct berval) );
1008           BER_BVZERO( bva );
1009           idx.bv_val = ibuf;
1010           if ( sys ) {
1011                     idx.bv_len = 0;
1012                     ibuf[0] = '\0';
1013           }
1014           i = 0;
1015           for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) {
1016                     LDAPAttributeType lat, *latp;
1017                     if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break;
1018                     if ( at->sat_oidmacro || at->sat_soidmacro ) {
1019                               lat = at->sat_atype;
1020                               if ( at->sat_oidmacro )
1021                                         lat.at_oid = at->sat_oidmacro;
1022                               if ( at->sat_soidmacro )
1023                                         lat.at_syntax_oid = at->sat_soidmacro;
1024                               latp = &lat;
1025                     } else {
1026                               latp = &at->sat_atype;
1027                     }
1028                     if ( ldap_attributetype2bv( latp, &bv ) == NULL ) {
1029                               ber_bvarray_free( bva );
1030                     }
1031                     if ( !sys ) {
1032                               idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
1033                     }
1034                     bva[i].bv_len = idx.bv_len + bv.bv_len;
1035                     bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
1036                     strcpy( bva[i].bv_val, ibuf );
1037                     strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
1038                     i++;
1039                     bva[i].bv_val = NULL;
1040                     ldap_memfree( bv.bv_val );
1041                     if ( at == end ) break;
1042           }
1043           *res = bva;
1044 }
1045 
1046 int
at_schema_info(Entry * e)1047 at_schema_info( Entry *e )
1048 {
1049           AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes;
1050           AttributeType       *at;
1051           struct berval       val;
1052           struct berval       nval;
1053 
1054           LDAP_STAILQ_FOREACH(at,&attr_list,sat_next) {
1055                     if( at->sat_flags & SLAP_AT_HIDE ) continue;
1056 
1057                     if ( ldap_attributetype2bv( &at->sat_atype, &val ) == NULL ) {
1058                               return -1;
1059                     }
1060 
1061                     ber_str2bv( at->sat_oid, 0, 0, &nval );
1062 
1063                     if( attr_merge_one( e, ad_attributeTypes, &val, &nval ) )
1064                     {
1065                               return -1;
1066                     }
1067                     ldap_memfree( val.bv_val );
1068           }
1069           return 0;
1070 }
1071 
1072 int
register_at(const char * def,AttributeDescription ** rad,int dupok)1073 register_at( const char *def, AttributeDescription **rad, int dupok )
1074 {
1075           LDAPAttributeType *at;
1076           int code, freeit = 0;
1077           const char *err;
1078           AttributeDescription *ad = NULL;
1079 
1080           at = ldap_str2attributetype( def, &code, &err, LDAP_SCHEMA_ALLOW_ALL );
1081           if ( !at ) {
1082                     Debug( LDAP_DEBUG_ANY,
1083                               "register_at: AttributeType \"%s\": %s, %s\n",
1084                                         def, ldap_scherr2str(code), err );
1085                     return code;
1086           }
1087 
1088           code = at_add( at, 0, NULL, NULL, &err );
1089           if ( code ) {
1090                     if ( code == SLAP_SCHERR_ATTR_DUP && dupok ) {
1091                               freeit = 1;
1092 
1093                     } else {
1094                               Debug( LDAP_DEBUG_ANY,
1095                                         "register_at: AttributeType \"%s\": %s, %s\n",
1096                                         def, scherr2str(code), err );
1097                               ldap_attributetype_free( at );
1098                               return code;
1099                     }
1100           }
1101           code = slap_str2ad( at->at_names[0], &ad, &err );
1102           if ( freeit || code ) {
1103                     ldap_attributetype_free( at );
1104           } else {
1105                     ldap_memfree( at );
1106           }
1107           if ( code ) {
1108                     Debug( LDAP_DEBUG_ANY, "register_at: AttributeType \"%s\": %s\n",
1109                               def, err );
1110           }
1111           if ( rad ) *rad = ad;
1112           return code;
1113 }
1114