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