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