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 = ⪫
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