1 /* value.c - routines for dealing with values */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/value.c,v 1.96.2.6 2008/02/11 23:26:45 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 * Copyright (c) 1995 Regents of the University of Michigan.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms are permitted
21 * provided that this notice is preserved and that due credit is given
22 * to the University of Michigan at Ann Arbor. The name of the University
23 * may not be used to endorse or promote products derived from this
24 * software without specific prior written permission. This software
25 * is provided ``as is'' without express or implied warranty.
33 #include <ac/socket.h>
34 #include <ac/string.h>
49 if ( addvals
!= NULL
) {
50 for ( ; !BER_BVISNULL( &addvals
[nn
] ); nn
++ )
54 if ( *vals
== NULL
) {
55 *vals
= (BerVarray
) SLAP_MALLOC( (nn
+ 1)
56 * sizeof(struct berval
) );
58 Debug(LDAP_DEBUG_TRACE
,
59 "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 );
60 return LBER_ERROR_MEMORY
;
65 for ( n
= 0; !BER_BVISNULL( &(*vals
)[n
] ); n
++ ) {
68 *vals
= (BerVarray
) SLAP_REALLOC( (char *) *vals
,
69 (n
+ nn
+ 1) * sizeof(struct berval
) );
71 Debug(LDAP_DEBUG_TRACE
,
72 "value_add: SLAP_MALLOC failed.\n", 0, 0, 0 );
73 return LBER_ERROR_MEMORY
;
78 for ( n
= 0 ; n
< nn
; v2
++, addvals
++ ) {
79 ber_dupbv( v2
, addvals
);
80 if ( BER_BVISNULL( v2
) ) break;
90 struct berval
*addval
)
95 if ( *vals
== NULL
) {
96 *vals
= (BerVarray
) SLAP_MALLOC( 2 * sizeof(struct berval
) );
98 Debug(LDAP_DEBUG_TRACE
,
99 "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 );
100 return LBER_ERROR_MEMORY
;
105 for ( n
= 0; !BER_BVISNULL( &(*vals
)[n
] ); n
++ ) {
108 *vals
= (BerVarray
) SLAP_REALLOC( (char *) *vals
,
109 (n
+ 2) * sizeof(struct berval
) );
110 if( *vals
== NULL
) {
111 Debug(LDAP_DEBUG_TRACE
,
112 "value_add_one: SLAP_MALLOC failed.\n", 0, 0, 0 );
113 return LBER_ERROR_MEMORY
;
118 ber_dupbv(v2
, addval
);
126 int asserted_value_validate_normalize(
127 AttributeDescription
*ad
,
139 /* we expect the value to be in the assertion syntax */
140 assert( !SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage
) );
143 *text
= "inappropriate matching request";
144 return LDAP_INAPPROPRIATE_MATCHING
;
147 if( !mr
->smr_match
) {
148 *text
= "requested matching rule not supported";
149 return LDAP_INAPPROPRIATE_MATCHING
;
152 if( mr
->smr_syntax
->ssyn_pretty
) {
153 rc
= (mr
->smr_syntax
->ssyn_pretty
)( mr
->smr_syntax
, in
, &pval
, ctx
);
156 } else if ( mr
->smr_syntax
->ssyn_validate
) {
157 rc
= (mr
->smr_syntax
->ssyn_validate
)( mr
->smr_syntax
, in
);
160 *text
= "inappropriate matching request";
161 return LDAP_INAPPROPRIATE_MATCHING
;
164 if( rc
!= LDAP_SUCCESS
) {
165 *text
= "value does not conform to assertion syntax";
166 return LDAP_INVALID_SYNTAX
;
169 if( mr
->smr_normalize
) {
170 rc
= (mr
->smr_normalize
)(
171 usage
|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
,
172 ad
? ad
->ad_type
->sat_syntax
: NULL
,
175 if( pval
.bv_val
) ber_memfree_x( pval
.bv_val
, ctx
);
177 if( rc
!= LDAP_SUCCESS
) {
178 *text
= "unable to normalize value for matching";
179 return LDAP_INVALID_SYNTAX
;
182 } else if ( pval
.bv_val
!= NULL
) {
186 ber_dupbv_x( out
, in
, ctx
);
195 AttributeDescription
*ad
,
198 struct berval
*v1
, /* stored value */
199 void *v2
, /* assertion */
204 assert( mr
!= NULL
);
206 if( !mr
->smr_match
) {
207 return LDAP_INAPPROPRIATE_MATCHING
;
210 rc
= (mr
->smr_match
)( match
, flags
,
211 ad
->ad_type
->sat_syntax
, mr
, v1
, v2
);
217 AttributeDescription
*ad
,
225 struct berval nval
= BER_BVNULL
;
226 MatchingRule
*mr
= ad
->ad_type
->sat_equality
;
228 if( mr
== NULL
|| !mr
->smr_match
) {
229 return LDAP_INAPPROPRIATE_MATCHING
;
232 assert( SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( flags
) != 0 );
234 if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags
) &&
237 rc
= (mr
->smr_normalize
)(
238 flags
& (SLAP_MR_TYPE_MASK
|SLAP_MR_SUBTYPE_MASK
|SLAP_MR_VALUE_OF_SYNTAX
),
239 ad
->ad_type
->sat_syntax
,
240 mr
, val
, &nval
, ctx
);
242 if( rc
!= LDAP_SUCCESS
) {
243 return LDAP_INVALID_SYNTAX
;
247 for ( i
= 0; vals
[i
].bv_val
!= NULL
; i
++ ) {
251 rc
= value_match( &match
, ad
, mr
, flags
,
252 &vals
[i
], nval
.bv_val
== NULL
? val
: &nval
, &text
);
254 if( rc
== LDAP_SUCCESS
&& match
== 0 ) {
255 slap_sl_free( nval
.bv_val
, ctx
);
260 slap_sl_free( nval
.bv_val
, ctx
);
261 return LDAP_NO_SUCH_ATTRIBUTE
;
264 /* assign new indexes to an attribute's ordered values */
266 ordered_value_renumber( Attribute
*a
)
268 char *ptr
, ibuf
[64]; /* many digits */
269 struct berval ibv
, tmp
, vtmp
;
274 for (i
=0; i
<a
->a_numvals
; i
++) {
275 ibv
.bv_len
= sprintf(ibv
.bv_val
, "{%d}", i
);
277 if ( vtmp
.bv_val
[0] == '{' ) {
278 ptr
= ber_bvchr(&vtmp
, '}');
279 assert( ptr
!= NULL
);
281 vtmp
.bv_len
-= ptr
- vtmp
.bv_val
;
284 tmp
.bv_len
= ibv
.bv_len
+ vtmp
.bv_len
;
285 tmp
.bv_val
= ch_malloc( tmp
.bv_len
+ 1 );
286 strcpy( tmp
.bv_val
, ibv
.bv_val
);
287 AC_MEMCPY( tmp
.bv_val
+ ibv
.bv_len
, vtmp
.bv_val
, vtmp
.bv_len
);
288 tmp
.bv_val
[tmp
.bv_len
] = '\0';
289 ch_free( a
->a_vals
[i
].bv_val
);
292 if ( a
->a_nvals
&& a
->a_nvals
!= a
->a_vals
) {
293 vtmp
= a
->a_nvals
[i
];
294 if ( vtmp
.bv_val
[0] == '{' ) {
295 ptr
= ber_bvchr(&vtmp
, '}');
296 assert( ptr
!= NULL
);
298 vtmp
.bv_len
-= ptr
- vtmp
.bv_val
;
301 tmp
.bv_len
= ibv
.bv_len
+ vtmp
.bv_len
;
302 tmp
.bv_val
= ch_malloc( tmp
.bv_len
+ 1 );
303 strcpy( tmp
.bv_val
, ibv
.bv_val
);
304 AC_MEMCPY( tmp
.bv_val
+ ibv
.bv_len
, vtmp
.bv_val
, vtmp
.bv_len
);
305 tmp
.bv_val
[tmp
.bv_len
] = '\0';
306 ch_free( a
->a_nvals
[i
].bv_val
);
312 /* Sort the values in an X-ORDERED VALUES attribute.
313 * If the values have no index, index them in their given order.
314 * If the values have indexes, sort them.
315 * If some are indexed and some are not, return Error.
318 ordered_value_sort( Attribute
*a
, int do_renumber
)
321 int index
= 0, noindex
= 0, renumber
= 0, gotnvals
= 0;
324 if ( a
->a_nvals
&& a
->a_nvals
!= a
->a_vals
)
327 /* count attrs, look for index */
328 for (i
=0; a
->a_vals
[i
].bv_val
; i
++) {
329 if ( a
->a_vals
[i
].bv_val
[0] == '{' ) {
332 ptr
= ber_bvchr( &a
->a_vals
[i
], '}' );
334 return LDAP_INVALID_SYNTAX
;
336 return LDAP_INVALID_SYNTAX
;
340 return LDAP_INVALID_SYNTAX
;
345 /* If values have indexes, sort the values */
347 int *indexes
, j
, idx
;
351 /* Strip index from normalized values */
352 if ( !a
->a_nvals
|| a
->a_vals
== a
->a_nvals
) {
353 a
->a_nvals
= ch_malloc( (vals
+1)*sizeof(struct berval
));
354 BER_BVZERO(a
->a_nvals
+vals
);
355 for ( i
=0; i
<vals
; i
++ ) {
356 char *ptr
= ber_bvchr(&a
->a_vals
[i
], '}') + 1;
357 a
->a_nvals
[i
].bv_len
= a
->a_vals
[i
].bv_len
-
358 (ptr
- a
->a_vals
[i
].bv_val
);
359 a
->a_nvals
[i
].bv_val
= ch_malloc( a
->a_nvals
[i
].bv_len
+ 1);
360 strcpy(a
->a_nvals
[i
].bv_val
, ptr
);
363 for ( i
=0; i
<vals
; i
++ ) {
364 char *ptr
= ber_bvchr(&a
->a_nvals
[i
], '}') + 1;
365 a
->a_nvals
[i
].bv_len
-= ptr
- a
->a_nvals
[i
].bv_val
;
366 strcpy(a
->a_nvals
[i
].bv_val
, ptr
);
371 indexes
= ch_malloc( vals
* sizeof(int) );
372 for ( i
=0; i
<vals
; i
++) {
374 indexes
[i
] = strtol(a
->a_vals
[i
].bv_val
+1, &ptr
, 0);
377 return LDAP_INVALID_SYNTAX
;
382 for ( i
=1; i
<vals
; i
++ ) {
385 if ( gotnvals
) ntmp
= a
->a_nvals
[i
];
387 while ((j
> 0) && (indexes
[j
-1] > idx
)) {
388 indexes
[j
] = indexes
[j
-1];
389 a
->a_vals
[j
] = a
->a_vals
[j
-1];
390 if ( gotnvals
) a
->a_nvals
[j
] = a
->a_nvals
[j
-1];
395 if ( gotnvals
) a
->a_nvals
[j
] = ntmp
;
398 /* If range is not contiguous, must renumber */
399 if ( indexes
[0] != 0 || indexes
[vals
-1] != vals
-1 ) {
407 if ( do_renumber
&& renumber
)
408 ordered_value_renumber( a
);
414 * wrapper for validate function
415 * uses the validate function of the syntax after removing
416 * the index, if allowed and present
419 ordered_value_validate(
420 AttributeDescription
*ad
,
424 struct berval bv
= *in
;
426 assert( ad
->ad_type
->sat_syntax
!= NULL
);
427 assert( ad
->ad_type
->sat_syntax
->ssyn_validate
!= NULL
);
429 if ( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED
) {
431 /* Skip past the assertion index */
432 if ( bv
.bv_val
[0] == '{' ) {
435 ptr
= ber_bvchr( &bv
, '}' );
439 ns
.bv_val
= bv
.bv_val
+ 1;
440 ns
.bv_len
= ptr
- ns
.bv_val
;
442 if ( numericStringValidate( NULL
, &ns
) == LDAP_SUCCESS
) {
444 bv
.bv_len
-= ptr
- bv
.bv_val
;
447 /* If deleting by index, just succeed */
448 if ( mop
== LDAP_MOD_DELETE
&& BER_BVISEMPTY( &bv
) ) {
456 return ad
->ad_type
->sat_syntax
->ssyn_validate( ad
->ad_type
->sat_syntax
, in
);
460 * wrapper for pretty function
461 * uses the pretty function of the syntax after removing
462 * the index, if allowed and present; in case, it's prepended
463 * to the pretty value
466 ordered_value_pretty(
467 AttributeDescription
*ad
,
472 struct berval bv
= *val
,
476 assert( ad
->ad_type
->sat_syntax
!= NULL
);
477 assert( ad
->ad_type
->sat_syntax
->ssyn_pretty
!= NULL
);
478 assert( val
!= NULL
);
479 assert( out
!= NULL
);
481 if ( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED
) {
483 /* Skip past the assertion index */
484 if ( bv
.bv_val
[0] == '{' ) {
487 ptr
= ber_bvchr( &bv
, '}' );
491 ns
.bv_val
= bv
.bv_val
+ 1;
492 ns
.bv_len
= ptr
- ns
.bv_val
;
494 if ( numericStringValidate( NULL
, &ns
) == LDAP_SUCCESS
) {
498 idx
.bv_len
= ptr
- bv
.bv_val
;
500 bv
.bv_len
-= idx
.bv_len
;
509 rc
= ad
->ad_type
->sat_syntax
->ssyn_pretty( ad
->ad_type
->sat_syntax
, val
, out
, ctx
);
511 if ( rc
== LDAP_SUCCESS
&& !BER_BVISNULL( &idx
) ) {
514 out
->bv_len
= idx
.bv_len
+ bv
.bv_len
;
515 out
->bv_val
= ber_memalloc_x( out
->bv_len
+ 1, ctx
);
517 AC_MEMCPY( out
->bv_val
, idx
.bv_val
, idx
.bv_len
);
518 AC_MEMCPY( &out
->bv_val
[ idx
.bv_len
], bv
.bv_val
, bv
.bv_len
+ 1 );
520 ber_memfree_x( bv
.bv_val
, ctx
);
527 * wrapper for normalize function
528 * uses the normalize function of the attribute description equality rule
529 * after removing the index, if allowed and present; in case, it's
530 * prepended to the value
533 ordered_value_normalize(
535 AttributeDescription
*ad
,
538 struct berval
*normalized
,
541 struct berval bv
= *val
,
545 assert( ad
->ad_type
->sat_equality
!= NULL
);
546 assert( ad
->ad_type
->sat_equality
->smr_normalize
!= NULL
);
547 assert( val
!= NULL
);
548 assert( normalized
!= NULL
);
550 if ( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED
) {
552 /* Skip past the assertion index */
553 if ( bv
.bv_val
[ 0 ] == '{' ) {
556 ptr
= ber_bvchr( &bv
, '}' );
560 ns
.bv_val
= bv
.bv_val
+ 1;
561 ns
.bv_len
= ptr
- ns
.bv_val
;
563 if ( numericStringValidate( NULL
, &ns
) == LDAP_SUCCESS
) {
567 idx
.bv_len
= ptr
- bv
.bv_val
;
569 bv
.bv_len
-= idx
.bv_len
;
572 /* validator will already prevent this for Adds */
573 if ( BER_BVISEMPTY( &bv
)) {
574 ber_dupbv_x( normalized
, &idx
, ctx
);
583 rc
= ad
->ad_type
->sat_equality
->smr_normalize( usage
,
584 ad
->ad_type
->sat_syntax
, mr
, val
, normalized
, ctx
);
586 if ( rc
== LDAP_SUCCESS
&& !BER_BVISNULL( &idx
) ) {
589 normalized
->bv_len
= idx
.bv_len
+ bv
.bv_len
;
590 normalized
->bv_val
= ber_memalloc_x( normalized
->bv_len
+ 1, ctx
);
592 AC_MEMCPY( normalized
->bv_val
, idx
.bv_val
, idx
.bv_len
);
593 AC_MEMCPY( &normalized
->bv_val
[ idx
.bv_len
], bv
.bv_val
, bv
.bv_len
+ 1 );
595 ber_memfree_x( bv
.bv_val
, ctx
);
601 /* A wrapper for value match, handles Equality matches for attributes
602 * with ordered values.
607 AttributeDescription
*ad
,
610 struct berval
*v1
, /* stored value */
611 struct berval
*v2
, /* assertion */
614 struct berval bv1
, bv2
;
616 /* X-ORDERED VALUES equality matching:
617 * If (SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX) that means we are
618 * comparing two attribute values. In this case, we want to ignore
619 * the ordering index of both values, we just want to know if their
620 * main values are equal.
622 * If (SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX) then we are comparing
623 * an assertion against an attribute value.
624 * If the assertion has no index, the index of the value is ignored.
625 * If the assertion has only an index, the remainder of the value is
627 * If the assertion has index and value, both are compared.
629 if ( ad
->ad_type
->sat_flags
& SLAP_AT_ORDERED
) {
631 struct berval ns1
= BER_BVNULL
, ns2
= BER_BVNULL
;
636 /* Skip past the assertion index */
637 if ( bv2
.bv_val
[0] == '{' ) {
638 ptr
= ber_bvchr( &bv2
, '}' );
640 ns2
.bv_val
= bv2
.bv_val
+ 1;
641 ns2
.bv_len
= ptr
- ns2
.bv_val
;
643 if ( numericStringValidate( NULL
, &ns2
) == LDAP_SUCCESS
) {
645 bv2
.bv_len
-= ptr
- bv2
.bv_val
;
652 /* Skip past the attribute index */
653 if ( bv1
.bv_val
[0] == '{' ) {
654 ptr
= ber_bvchr( &bv1
, '}' );
656 ns1
.bv_val
= bv1
.bv_val
+ 1;
657 ns1
.bv_len
= ptr
- ns1
.bv_val
;
659 if ( numericStringValidate( NULL
, &ns1
) == LDAP_SUCCESS
) {
661 bv1
.bv_len
-= ptr
- bv1
.bv_val
;
668 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags
)) {
669 if ( !BER_BVISNULL( &ns2
) && !BER_BVISNULL( &ns1
) ) {
670 /* compare index values first */
671 (void)octetStringOrderingMatch( match
, 0, NULL
, NULL
, &ns1
, &ns2
);
673 /* If not equal, or we're only comparing the index,
676 if ( *match
!= 0 || BER_BVISEMPTY( &bv2
) ) {
684 if ( !mr
|| !mr
->smr_match
) {
685 *match
= ber_bvcmp( v1
, v2
);
689 return value_match( match
, ad
, mr
, flags
, v1
, v2
, text
);
695 AttributeDescription
*ad
,
701 int i
, j
, k
, anum
, vnum
;
702 BerVarray
new, nnew
= NULL
;
705 for (i
=0; !BER_BVISNULL( vals
+i
); i
++) ;
709 ordered_value_sort( a
, 0 );
712 for ( ap
=&e
->e_attrs
; *ap
; ap
= &(*ap
)->a_next
) ;
713 a
= attr_alloc( ad
);
718 new = ch_malloc( (anum
+vnum
+1) * sizeof(struct berval
));
720 /* sanity check: if normalized modifications come in, either
721 * no values are present or normalized existing values differ
722 * from non-normalized; if no normalized modifications come in,
723 * either no values are present or normalized existing values
724 * don't differ from non-normalized */
725 if ( nvals
!= NULL
) {
726 assert( nvals
!= vals
);
727 assert( a
->a_nvals
== NULL
|| a
->a_nvals
!= a
->a_vals
);
730 assert( a
->a_nvals
== NULL
|| a
->a_nvals
== a
->a_vals
);
733 if ( ( a
->a_nvals
&& a
->a_nvals
!= a
->a_vals
) || nvals
!= NULL
) {
734 nnew
= ch_malloc( (anum
+vnum
+1) * sizeof(struct berval
));
735 /* Shouldn't happen... */
736 if ( !nvals
) nvals
= vals
;
739 AC_MEMCPY( new, a
->a_vals
, anum
* sizeof(struct berval
));
740 if ( nnew
&& a
->a_nvals
)
741 AC_MEMCPY( nnew
, a
->a_nvals
, anum
* sizeof(struct berval
));
744 for (i
=0; i
<vnum
; i
++) {
748 if ( vals
[i
].bv_val
[0] == '{' ) {
749 /* FIXME: strtol() could go past end... */
750 k
= strtol( vals
[i
].bv_val
+ 1, &next
, 0 );
751 if ( next
== vals
[i
].bv_val
+ 1 ||
753 next
- vals
[i
].bv_val
> vals
[i
].bv_len
)
759 if ( k
> anum
) k
= -1;
761 /* No index, or index is greater than current number of
762 * values, just tack onto the end
765 ber_dupbv( new+anum
, vals
+i
);
766 if ( nnew
) ber_dupbv( nnew
+anum
, nvals
+i
);
768 /* Indexed, push everything else down one and insert */
770 for (j
=anum
; j
>k
; j
--) {
772 if ( nnew
) nnew
[j
] = nnew
[j
-1];
774 ber_dupbv( new+k
, vals
+i
);
775 if ( nnew
) ber_dupbv( nnew
+k
, nvals
+i
);
779 BER_BVZERO( new+anum
);
780 ch_free( a
->a_vals
);
783 BER_BVZERO( nnew
+anum
);
784 ch_free( a
->a_nvals
);
787 a
->a_nvals
= a
->a_vals
;
791 ordered_value_renumber( a
);