1 /* component.c -- Component Filter Match Routines */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/component.c,v 1.31.2.3 2008/02/11 23:26:43 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2008 The OpenLDAP Foundation.
6 * Portions Copyright 2004 by IBM Corporation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
21 #include <ac/socket.h>
27 #ifdef LDAP_COMP_MATCH
29 #include "component.h"
32 * Following function pointers are initialized
33 * when a component module is loaded
35 alloc_nibble_func
* nibble_mem_allocator
= NULL
;
36 free_nibble_func
* nibble_mem_free
= NULL
;
37 convert_attr_to_comp_func
* attr_converter
= NULL
;
38 convert_assert_to_comp_func
* assert_converter
= NULL
;
39 free_component_func
* component_destructor
= NULL
;
40 test_component_func
* test_components
= NULL
;
41 test_membership_func
* is_aliased_attribute
= NULL
;
42 component_encoder_func
* component_encoder
= NULL
;
43 get_component_info_func
* get_component_description
= NULL
;
44 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
45 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
46 #define MAX_LDAP_STR_LEN 128
49 peek_componentId_type( ComponentAssertionValue
* cav
);
52 strip_cav_str( ComponentAssertionValue
* cav
, char* str
);
55 peek_cav_str( ComponentAssertionValue
* cav
, char* str
);
58 parse_comp_filter( Operation
* op
, ComponentAssertionValue
* cav
,
59 ComponentFilter
** filt
, const char** text
);
62 free_comp_filter( ComponentFilter
* f
);
65 test_comp_filter( Syntax
*syn
, ComponentSyntaxInfo
*a
, ComponentFilter
*f
);
68 componentCertificateValidate(
76 componentFilterValidate(
84 allComponentsValidate(
92 componentFilterMatch (
100 ComponentSyntaxInfo
*csi_attr
= (ComponentSyntaxInfo
*)value
;
101 MatchingRuleAssertion
* ma
= (MatchingRuleAssertion
*)assertedValue
;
104 if ( !mr
|| !ma
->ma_cf
) return LDAP_INAPPROPRIATE_MATCHING
;
106 /* Check if the component module is loaded */
107 if ( !attr_converter
|| !nibble_mem_allocator
) {
111 rc
= test_comp_filter( syntax
, csi_attr
, ma
->ma_cf
);
113 if ( rc
== LDAP_COMPARE_TRUE
) {
117 else if ( rc
== LDAP_COMPARE_FALSE
) {
122 return LDAP_INAPPROPRIATE_MATCHING
;
127 directoryComponentsMatch(
132 struct berval
*value
,
133 void *assertedValue
)
135 /* Only for registration */
146 struct berval
*value
,
147 void *assertedValue
)
149 /* Only for registration */
155 slapd_ber2cav( struct berval
* bv
, ComponentAssertionValue
* cav
)
157 cav
->cav_ptr
= cav
->cav_buf
= bv
->bv_val
;
158 cav
->cav_end
= bv
->bv_val
+ bv
->bv_len
;
164 dup_comp_ref ( Operation
* op
, ComponentReference
* cr
)
166 ComponentReference
* dup_cr
;
167 ComponentId
* ci_curr
;
168 ComponentId
** ci_temp
;
170 dup_cr
= op
->o_tmpalloc( sizeof( ComponentReference
), op
->o_tmpmemctx
);
172 dup_cr
->cr_len
= cr
->cr_len
;
173 dup_cr
->cr_string
= cr
->cr_string
;
175 ci_temp
= &dup_cr
->cr_list
;
176 ci_curr
= cr
->cr_list
;
178 for ( ; ci_curr
!= NULL
;
179 ci_curr
= ci_curr
->ci_next
, ci_temp
= &(*ci_temp
)->ci_next
)
181 *ci_temp
= op
->o_tmpalloc( sizeof( ComponentId
), op
->o_tmpmemctx
);
182 if ( !*ci_temp
) return NULL
;
183 **ci_temp
= *ci_curr
;
186 dup_cr
->cr_curr
= dup_cr
->cr_list
;
192 dup_comp_filter_list (
195 ComponentFilter
* in_f
,
196 ComponentFilter
** out_f
)
198 ComponentFilter
**new, *f
;
202 for ( f
= in_f
; f
!= NULL
; f
= f
->cf_next
) {
203 rc
= dup_comp_filter( op
, bv
, f
, new );
204 if ( rc
!= LDAP_SUCCESS
) {
207 new = &(*new)->cf_next
;
213 get_len_of_next_assert_value ( struct berval
* bv
, char separator
)
217 if ( (bv
->bv_val
[ i
] == separator
) || ( i
>= bv
->bv_len
) )
221 bv
->bv_val
+= (i
+ 1);
222 bv
->bv_len
-= (i
+ 1);
227 dup_comp_filter_item (
229 struct berval
* assert_bv
,
230 ComponentAssertion
* in_ca
,
231 ComponentAssertion
** out_ca
)
235 if ( !in_ca
->ca_comp_ref
) return SLAPD_DISCONNECT
;
237 *out_ca
= op
->o_tmpalloc( sizeof( ComponentAssertion
), op
->o_tmpmemctx
);
238 if ( !(*out_ca
) ) return LDAP_NO_MEMORY
;
240 (*out_ca
)->ca_comp_data
.cd_tree
= NULL
;
241 (*out_ca
)->ca_comp_data
.cd_mem_op
= NULL
;
243 (*out_ca
)->ca_comp_ref
= dup_comp_ref ( op
, in_ca
->ca_comp_ref
);
244 (*out_ca
)->ca_use_def
= 0;
245 (*out_ca
)->ca_ma_rule
= in_ca
->ca_ma_rule
;
247 (*out_ca
)->ca_ma_value
.bv_val
= assert_bv
->bv_val
;
248 len
= get_len_of_next_assert_value ( assert_bv
, '$' );
249 if ( len
<= 0 ) return SLAPD_DISCONNECT
;
250 (*out_ca
)->ca_ma_value
.bv_len
= len
;
259 ComponentFilter
*in_f
,
260 ComponentFilter
**out_f
)
263 ComponentFilter dup_f
= {0};
265 if ( !in_f
) return LDAP_PROTOCOL_ERROR
;
267 switch ( in_f
->cf_choice
) {
268 case LDAP_COMP_FILTER_AND
:
269 rc
= dup_comp_filter_list( op
, bv
, in_f
->cf_and
, &dup_f
.cf_and
);
270 dup_f
.cf_choice
= LDAP_COMP_FILTER_AND
;
272 case LDAP_COMP_FILTER_OR
:
273 rc
= dup_comp_filter_list( op
, bv
, in_f
->cf_or
, &dup_f
.cf_or
);
274 dup_f
.cf_choice
= LDAP_COMP_FILTER_OR
;
276 case LDAP_COMP_FILTER_NOT
:
277 rc
= dup_comp_filter( op
, bv
, in_f
->cf_not
, &dup_f
.cf_not
);
278 dup_f
.cf_choice
= LDAP_COMP_FILTER_NOT
;
280 case LDAP_COMP_FILTER_ITEM
:
281 rc
= dup_comp_filter_item( op
, bv
, in_f
->cf_ca
,&dup_f
.cf_ca
);
282 dup_f
.cf_choice
= LDAP_COMP_FILTER_ITEM
;
285 rc
= LDAP_PROTOCOL_ERROR
;
288 if ( rc
== LDAP_SUCCESS
) {
289 *out_f
= op
->o_tmpalloc( sizeof(dup_f
), op
->o_tmpmemctx
);
297 get_aliased_filter_aa ( Operation
* op
, AttributeAssertion
* a_assert
, AttributeAliasing
* aa
, const char** text
)
299 struct berval assert_bv
;
301 Debug( LDAP_DEBUG_FILTER
, "get_aliased_filter\n", 0, 0, 0 );
304 return LDAP_PROTOCOL_ERROR
;
306 assert_bv
= a_assert
->aa_value
;
308 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
309 * the component assertion value in assert_bv
310 * Multiple values may be separated with '$'
312 return dup_comp_filter ( op
, &assert_bv
, aa
->aa_cf
, &a_assert
->aa_cf
);
316 get_aliased_filter( Operation
* op
,
317 MatchingRuleAssertion
* ma
, AttributeAliasing
* aa
,
320 struct berval assert_bv
;
322 Debug( LDAP_DEBUG_FILTER
, "get_aliased_filter\n", 0, 0, 0 );
324 if ( !aa
->aa_cf
) return LDAP_PROTOCOL_ERROR
;
326 assert_bv
= ma
->ma_value
;
327 /* Attribute Description is replaced with aliased one */
328 ma
->ma_desc
= aa
->aa_aliased_ad
;
329 ma
->ma_rule
= aa
->aa_mr
;
331 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
332 * the component assertion value in assert_bv
333 * Multiple values may be separated with '$'
335 return dup_comp_filter ( op
, &assert_bv
, aa
->aa_cf
, &ma
->ma_cf
);
339 get_comp_filter( Operation
* op
, struct berval
* bv
,
340 ComponentFilter
** filt
, const char **text
)
342 ComponentAssertionValue cav
;
345 Debug( LDAP_DEBUG_FILTER
, "get_comp_filter\n", 0, 0, 0 );
346 if ( (rc
= slapd_ber2cav(bv
, &cav
) ) != LDAP_SUCCESS
) {
349 rc
= parse_comp_filter( op
, &cav
, filt
, text
);
350 bv
->bv_val
= cav
.cav_ptr
;
356 eat_whsp( ComponentAssertionValue
* cav
)
358 for ( ; ( *cav
->cav_ptr
== ' ' ) && ( cav
->cav_ptr
< cav
->cav_end
) ; ) {
364 cav_cur_len( ComponentAssertionValue
* cav
)
366 return cav
->cav_end
- cav
->cav_ptr
;
370 comp_first_element( ComponentAssertionValue
* cav
)
373 if ( cav_cur_len( cav
) >= 8 && strncmp( cav
->cav_ptr
, "item", 4 ) == 0 ) {
374 return LDAP_COMP_FILTER_ITEM
;
376 } else if ( cav_cur_len( cav
) >= 7 &&
377 strncmp( cav
->cav_ptr
, "and", 3 ) == 0 )
379 return LDAP_COMP_FILTER_AND
;
381 } else if ( cav_cur_len( cav
) >= 6 &&
382 strncmp( cav
->cav_ptr
, "or" , 2 ) == 0 )
384 return LDAP_COMP_FILTER_OR
;
386 } else if ( cav_cur_len( cav
) >= 7 &&
387 strncmp( cav
->cav_ptr
, "not", 3 ) == 0 )
389 return LDAP_COMP_FILTER_NOT
;
392 return LDAP_COMP_FILTER_UNDEFINED
;
397 comp_next_element( ComponentAssertionValue
* cav
)
400 if ( *(cav
->cav_ptr
) == ',' ) {
401 /* move pointer to the next CA */
403 return comp_first_element( cav
);
405 else return LDAP_COMP_FILTER_UNDEFINED
;
409 get_comp_filter_list( Operation
*op
, ComponentAssertionValue
*cav
,
410 ComponentFilter
** f
, const char** text
)
412 ComponentFilter
**new;
416 Debug( LDAP_DEBUG_FILTER
, "get_comp_filter_list\n", 0, 0, 0 );
418 for ( tag
= comp_first_element( cav
);
419 tag
!= LDAP_COMP_FILTER_UNDEFINED
;
420 tag
= comp_next_element( cav
) )
422 err
= parse_comp_filter( op
, cav
, new, text
);
423 if ( err
!= LDAP_SUCCESS
) return ( err
);
424 new = &(*new)->cf_next
;
428 return( LDAP_SUCCESS
);
432 get_componentId( Operation
*op
, ComponentAssertionValue
* cav
,
433 ComponentId
** cid
, const char** text
)
439 type
= peek_componentId_type( cav
);
441 Debug( LDAP_DEBUG_FILTER
, "get_compId [%lu]\n",
442 (unsigned long) type
, 0, 0 );
447 case LDAP_COMPREF_IDENTIFIER
:
448 _cid
.ci_val
.ci_identifier
.bv_val
= cav
->cav_ptr
;
449 for( ;cav
->cav_ptr
[len
] != ' ' && cav
->cav_ptr
[len
] != '\0' &&
450 cav
->cav_ptr
[len
] != '.' && cav
->cav_ptr
[len
] != '\"' ; len
++ );
451 _cid
.ci_val
.ci_identifier
.bv_len
= len
;
454 case LDAP_COMPREF_FROM_BEGINNING
:
455 for( ;cav
->cav_ptr
[len
] != ' ' && cav
->cav_ptr
[len
] != '\0' &&
456 cav
->cav_ptr
[len
] != '.' && cav
->cav_ptr
[len
] != '\"' ; len
++ );
457 _cid
.ci_val
.ci_from_beginning
= strtol( cav
->cav_ptr
, NULL
, 0 );
460 case LDAP_COMPREF_FROM_END
:
461 for( ;cav
->cav_ptr
[len
] != ' ' && cav
->cav_ptr
[len
] != '\0' &&
462 cav
->cav_ptr
[len
] != '.' && cav
->cav_ptr
[len
] != '\"' ; len
++ );
463 _cid
.ci_val
.ci_from_end
= strtol( cav
->cav_ptr
, NULL
, 0 );
466 case LDAP_COMPREF_COUNT
:
467 _cid
.ci_val
.ci_count
= 0;
470 case LDAP_COMPREF_CONTENT
:
471 _cid
.ci_val
.ci_content
= 1;
472 cav
->cav_ptr
+= strlen("content");
474 case LDAP_COMPREF_SELECT
:
475 if ( cav
->cav_ptr
[len
] != '(' ) return LDAP_COMPREF_UNDEFINED
;
476 for( ;cav
->cav_ptr
[len
] != ' ' && cav
->cav_ptr
[len
] != '\0' &&
477 cav
->cav_ptr
[len
] != '\"' && cav
->cav_ptr
[len
] != ')'
479 _cid
.ci_val
.ci_select_value
.bv_val
= cav
->cav_ptr
+ 1;
480 _cid
.ci_val
.ci_select_value
.bv_len
= len
- 1 ;
481 cav
->cav_ptr
+= len
+ 1;
483 case LDAP_COMPREF_ALL
:
484 _cid
.ci_val
.ci_all
= '*';
488 return LDAP_COMPREF_UNDEFINED
;
492 *cid
= op
->o_tmpalloc( sizeof( ComponentId
), op
->o_tmpmemctx
);
494 *cid
= malloc( sizeof( ComponentId
) );
501 peek_componentId_type( ComponentAssertionValue
* cav
)
505 if ( cav
->cav_ptr
[0] == '-' ) {
506 return LDAP_COMPREF_FROM_END
;
508 } else if ( cav
->cav_ptr
[0] == '(' ) {
509 return LDAP_COMPREF_SELECT
;
511 } else if ( cav
->cav_ptr
[0] == '*' ) {
512 return LDAP_COMPREF_ALL
;
514 } else if ( cav
->cav_ptr
[0] == '0' ) {
515 return LDAP_COMPREF_COUNT
;
517 } else if ( cav
->cav_ptr
[0] > '0' && cav
->cav_ptr
[0] <= '9' ) {
518 return LDAP_COMPREF_FROM_BEGINNING
;
520 } else if ( (cav
->cav_end
- cav
->cav_ptr
) >= 7 &&
521 strncmp(cav
->cav_ptr
,"content",7) == 0 )
523 return LDAP_COMPREF_CONTENT
;
524 } else if ( (cav
->cav_ptr
[0] >= 'a' && cav
->cav_ptr
[0] <= 'z') ||
525 (cav
->cav_ptr
[0] >= 'A' && cav
->cav_ptr
[0] <= 'Z') )
527 return LDAP_COMPREF_IDENTIFIER
;
530 return LDAP_COMPREF_UNDEFINED
;
534 comp_next_id( ComponentAssertionValue
* cav
)
536 if ( *(cav
->cav_ptr
) == '.' ) {
538 return LDAP_COMPREF_DEFINED
;
541 return LDAP_COMPREF_UNDEFINED
;
547 get_component_reference(
549 ComponentAssertionValue
* cav
,
550 ComponentReference
** cr
,
555 ComponentReference
* ca_comp_ref
;
556 ComponentId
** cr_list
;
561 start
= cav
->cav_ptr
;
562 if ( ( rc
= strip_cav_str( cav
,"\"") ) != LDAP_SUCCESS
) return rc
;
564 ca_comp_ref
= op
->o_tmpalloc( sizeof( ComponentReference
),
567 ca_comp_ref
= malloc( sizeof( ComponentReference
) );
570 if ( !ca_comp_ref
) return LDAP_NO_MEMORY
;
572 cr_list
= &ca_comp_ref
->cr_list
;
574 for ( type
= peek_componentId_type( cav
) ; type
!= LDAP_COMPREF_UNDEFINED
575 ; type
= comp_next_id( cav
), count
++ )
577 rc
= get_componentId( op
, cav
, cr_list
, text
);
578 if ( rc
== LDAP_SUCCESS
) {
579 if ( count
== 0 ) ca_comp_ref
->cr_curr
= ca_comp_ref
->cr_list
;
580 cr_list
= &(*cr_list
)->ci_next
;
582 } else if ( rc
== LDAP_COMPREF_UNDEFINED
) {
584 op
->o_tmpfree( ca_comp_ref
, op
->o_tmpmemctx
);
591 ca_comp_ref
->cr_len
= count
;
593 if ( ( rc
= strip_cav_str( cav
,"\"") ) != LDAP_SUCCESS
) {
595 op
->o_tmpfree( ca_comp_ref
, op
->o_tmpmemctx
);
605 (*cr
)->cr_string
.bv_val
= start
;
606 (*cr
)->cr_string
.bv_len
= end
- start
+ 1;
612 insert_component_reference(
613 ComponentReference
*cr
,
614 ComponentReference
** cr_list
)
616 if ( !cr
) return LDAP_PARAM_ERROR
;
622 cr
->cr_next
= *cr_list
;
629 * If there is '.' in the name of a given attribute
630 * the first '.'- following characters are considered
631 * as a component reference of the attribute
632 * EX) userCertificate.toBeSigned.serialNumber
633 * attribute : userCertificate
634 * component reference : toBeSigned.serialNumber
637 is_component_reference( char* attr
) {
639 for ( i
=0; attr
[i
] != '\0' ; i
++ ) {
640 if ( attr
[i
] == '.' ) return (1);
646 extract_component_reference(
648 ComponentReference
** cr
)
653 ComponentAssertionValue cav
;
656 for ( i
=0; attr
[i
] != '\0' ; i
++ ) {
657 if ( attr
[i
] == '.' ) break;
660 if (attr
[i
] != '.' ) return LDAP_PARAM_ERROR
;
663 cr_ptr
= attr
+ i
+ 1 ;
664 cr_len
= strlen ( cr_ptr
);
665 if ( cr_len
<= 0 ) return LDAP_PARAM_ERROR
;
667 /* enclosed between double quotes*/
668 cav
.cav_ptr
= cav
.cav_buf
= ch_malloc (cr_len
+2);
669 memcpy( cav
.cav_buf
+1, cr_ptr
, cr_len
);
670 cav
.cav_buf
[0] = '"';
671 cav
.cav_buf
[cr_len
+1] = '"';
672 cav
.cav_end
= cr_ptr
+ cr_len
+ 2;
674 rc
= get_component_reference ( NULL
, &cav
, cr
, (const char**)text
);
675 if ( rc
!= LDAP_SUCCESS
) return rc
;
676 (*cr
)->cr_string
.bv_val
= cav
.cav_buf
;
677 (*cr
)->cr_string
.bv_len
= cr_len
+ 2;
683 get_ca_use_default( Operation
*op
,
684 ComponentAssertionValue
* cav
,
685 int* ca_use_def
, const char** text
)
687 strip_cav_str( cav
, "useDefaultValues" );
689 if ( peek_cav_str( cav
, "TRUE" ) == LDAP_SUCCESS
) {
690 strip_cav_str( cav
, "TRUE" );
693 } else if ( peek_cav_str( cav
, "FALSE" ) == LDAP_SUCCESS
) {
694 strip_cav_str( cav
, "FALSE" );
698 return LDAP_INVALID_SYNTAX
;
705 get_matching_rule( Operation
*op
, ComponentAssertionValue
* cav
,
706 MatchingRule
** mr
, const char** text
)
709 struct berval rule_text
= { 0L, NULL
};
713 for ( ; ; count
++ ) {
714 if ( cav
->cav_ptr
[count
] == ' ' || cav
->cav_ptr
[count
] == ',' ||
715 cav
->cav_ptr
[count
] == '\0' || cav
->cav_ptr
[count
] == '{' ||
716 cav
->cav_ptr
[count
] == '}' || cav
->cav_ptr
[count
] == '\n' )
723 *text
= "component matching rule not recognized";
724 return LDAP_INAPPROPRIATE_MATCHING
;
727 rule_text
.bv_len
= count
;
728 rule_text
.bv_val
= cav
->cav_ptr
;
729 *mr
= mr_bvfind( &rule_text
);
730 cav
->cav_ptr
+= count
;
731 Debug( LDAP_DEBUG_FILTER
, "get_matching_rule: %s\n",
732 (*mr
)->smr_mrule
.mr_oid
, 0, 0 );
734 *text
= "component matching rule not recognized";
735 return LDAP_INAPPROPRIATE_MATCHING
;
741 get_GSER_value( ComponentAssertionValue
* cav
, struct berval
* bv
)
743 int count
, sequent_dquote
, unclosed_brace
, succeed
;
747 * Four cases of GSER <Values>
749 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
750 * 2) '...'B or '...'H :
751 * BitStringVal, OctetStringVal
753 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
754 * 4) Between two white spaces
755 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
759 if ( cav
->cav_ptr
[0] == '"' ) {
760 for( count
= 1, sequent_dquote
= 0 ; ; count
++ ) {
761 /* In order to find escaped double quote */
762 if ( cav
->cav_ptr
[count
] == '"' ) sequent_dquote
++;
763 else sequent_dquote
= 0;
765 if ( cav
->cav_ptr
[count
] == '\0' ||
766 (cav
->cav_ptr
+count
) > cav
->cav_end
)
771 if ( ( cav
->cav_ptr
[count
] == '"' &&
772 cav
->cav_ptr
[count
-1] != '"') ||
773 ( sequent_dquote
> 2 && (sequent_dquote
%2) == 1 ) )
780 if ( !succeed
|| cav
->cav_ptr
[count
] != '"' ) {
781 return LDAP_FILTER_ERROR
;
784 bv
->bv_val
= cav
->cav_ptr
+ 1;
785 bv
->bv_len
= count
- 1; /* exclude '"' */
787 } else if ( cav
->cav_ptr
[0] == '\'' ) {
788 for( count
= 1 ; ; count
++ ) {
789 if ( cav
->cav_ptr
[count
] == '\0' ||
790 (cav
->cav_ptr
+count
) > cav
->cav_end
)
794 if ((cav
->cav_ptr
[count
-1] == '\'' && cav
->cav_ptr
[count
] == 'B') ||
795 (cav
->cav_ptr
[count
-1] == '\'' && cav
->cav_ptr
[count
] == 'H') )
803 !(cav
->cav_ptr
[count
] == 'H' || cav
->cav_ptr
[count
] == 'B') )
805 return LDAP_FILTER_ERROR
;
808 bv
->bv_val
= cav
->cav_ptr
+ 1;/*the next to '"' */
809 bv
->bv_len
= count
- 2;/* exclude "'H" or "'B" */
811 } else if ( cav
->cav_ptr
[0] == '{' ) {
812 for( count
= 1, unclosed_brace
= 1 ; ; count
++ ) {
813 if ( cav
->cav_ptr
[count
] == '{' ) unclosed_brace
++;
814 if ( cav
->cav_ptr
[count
] == '}' ) unclosed_brace
--;
816 if ( cav
->cav_ptr
[count
] == '\0' ||
817 (cav
->cav_ptr
+count
) > cav
->cav_end
)
821 if ( unclosed_brace
== 0 ) {
827 if ( !succeed
|| cav
->cav_ptr
[count
] != '}' ) return LDAP_FILTER_ERROR
;
829 bv
->bv_val
= cav
->cav_ptr
+ 1;/*the next to '"' */
830 bv
->bv_len
= count
- 1;/* exclude "'B" */
834 /*Find following white space where the value is ended*/
835 for( count
= 1 ; ; count
++ ) {
836 if ( cav
->cav_ptr
[count
] == '\0' ||
837 cav
->cav_ptr
[count
] == ' ' || cav
->cav_ptr
[count
] == '}' ||
838 cav
->cav_ptr
[count
] == '{' ||
839 (cav
->cav_ptr
+count
) > cav
->cav_end
)
844 bv
->bv_val
= cav
->cav_ptr
;
848 cav
->cav_ptr
+= bv
->bv_len
;
853 get_matching_value( Operation
*op
, ComponentAssertion
* ca
,
854 ComponentAssertionValue
* cav
, struct berval
* bv
,
857 if ( !(ca
->ca_ma_rule
->smr_usage
& (SLAP_MR_COMPONENT
)) ) {
858 if ( get_GSER_value( cav
, bv
) != LDAP_SUCCESS
) {
859 return LDAP_FILTER_ERROR
;
863 /* embeded componentFilterMatch Description */
864 bv
->bv_val
= cav
->cav_ptr
;
865 bv
->bv_len
= cav_cur_len( cav
);
871 /* Don't move the position pointer, just peek given string */
873 peek_cav_str( ComponentAssertionValue
* cav
, char* str
)
876 if ( cav_cur_len( cav
) >= strlen( str
) &&
877 strncmp( cav
->cav_ptr
, str
, strlen( str
) ) == 0 )
882 return LDAP_INVALID_SYNTAX
;
886 strip_cav_str( ComponentAssertionValue
* cav
, char* str
)
889 if ( cav_cur_len( cav
) >= strlen( str
) &&
890 strncmp( cav
->cav_ptr
, str
, strlen( str
) ) == 0 )
892 cav
->cav_ptr
+= strlen( str
);
896 return LDAP_INVALID_SYNTAX
;
900 * TAG : "item", "and", "or", "not"
903 strip_cav_tag( ComponentAssertionValue
* cav
)
907 if ( cav_cur_len( cav
) >= 8 && strncmp( cav
->cav_ptr
, "item", 4 ) == 0 ) {
908 strip_cav_str( cav
, "item:" );
909 return LDAP_COMP_FILTER_ITEM
;
911 } else if ( cav_cur_len( cav
) >= 7 &&
912 strncmp( cav
->cav_ptr
, "and", 3 ) == 0 )
914 strip_cav_str( cav
, "and:" );
915 return LDAP_COMP_FILTER_AND
;
917 } else if ( cav_cur_len( cav
) >= 6 &&
918 strncmp( cav
->cav_ptr
, "or" , 2 ) == 0 )
920 strip_cav_str( cav
, "or:" );
921 return LDAP_COMP_FILTER_OR
;
923 } else if ( cav_cur_len( cav
) >= 7 &&
924 strncmp( cav
->cav_ptr
, "not", 3 ) == 0 )
926 strip_cav_str( cav
, "not:" );
927 return LDAP_COMP_FILTER_NOT
;
934 * when encoding, "item" is denotation of ComponentAssertion
935 * ComponentAssertion :: SEQUENCE {
936 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
937 * useDefaultValues BOOLEAN DEFAULT TRUE,
938 * rule MATCHING-RULE.&id,
939 * value MATCHING-RULE.&AssertionType }
942 get_item( Operation
*op
, ComponentAssertionValue
* cav
, ComponentAssertion
** ca
,
946 ComponentAssertion
* _ca
;
950 Debug( LDAP_DEBUG_FILTER
, "get_item \n", 0, 0, 0 );
952 _ca
= op
->o_tmpalloc( sizeof( ComponentAssertion
), op
->o_tmpmemctx
);
954 _ca
= malloc( sizeof( ComponentAssertion
) );
956 if ( !_ca
) return LDAP_NO_MEMORY
;
958 _ca
->ca_comp_data
.cd_tree
= NULL
;
959 _ca
->ca_comp_data
.cd_mem_op
= NULL
;
961 rc
= peek_cav_str( cav
, "component" );
962 if ( rc
== LDAP_SUCCESS
) {
963 strip_cav_str( cav
, "component" );
964 rc
= get_component_reference( op
, cav
, &_ca
->ca_comp_ref
, text
);
965 if ( rc
!= LDAP_SUCCESS
) {
967 op
->o_tmpfree( _ca
, op
->o_tmpmemctx
);
970 return LDAP_INVALID_SYNTAX
;
972 if ( ( rc
= strip_cav_str( cav
,",") ) != LDAP_SUCCESS
)
975 _ca
->ca_comp_ref
= NULL
;
978 rc
= peek_cav_str( cav
, "useDefaultValues");
979 if ( rc
== LDAP_SUCCESS
) {
980 rc
= get_ca_use_default( op
, cav
, &_ca
->ca_use_def
, text
);
981 if ( rc
!= LDAP_SUCCESS
) {
983 op
->o_tmpfree( _ca
, op
->o_tmpmemctx
);
986 return LDAP_INVALID_SYNTAX
;
988 if ( ( rc
= strip_cav_str( cav
,",") ) != LDAP_SUCCESS
)
991 else _ca
->ca_use_def
= 1;
993 if ( !( strip_cav_str( cav
, "rule" ) == LDAP_SUCCESS
&&
994 get_matching_rule( op
, cav
, &_ca
->ca_ma_rule
, text
) == LDAP_SUCCESS
)) {
996 op
->o_tmpfree( _ca
, op
->o_tmpmemctx
);
999 return LDAP_INAPPROPRIATE_MATCHING
;
1002 if ( ( rc
= strip_cav_str( cav
,",") ) != LDAP_SUCCESS
)
1004 if ( !(strip_cav_str( cav
, "value" ) == LDAP_SUCCESS
&&
1005 get_matching_value( op
, _ca
, cav
,&value
,text
) == LDAP_SUCCESS
)) {
1007 op
->o_tmpfree( _ca
, op
->o_tmpmemctx
);
1010 return LDAP_INVALID_SYNTAX
;
1014 * Normalize the value of this component assertion when the matching
1015 * rule is one of existing matching rules
1017 mr
= _ca
->ca_ma_rule
;
1018 if ( op
&& !(mr
->smr_usage
& (SLAP_MR_COMPONENT
)) && mr
->smr_normalize
) {
1020 value
.bv_val
[value
.bv_len
] = '\0';
1021 rc
= mr
->smr_normalize (
1022 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
,
1024 &value
, &_ca
->ca_ma_value
, op
->o_tmpmemctx
);
1025 if ( rc
!= LDAP_SUCCESS
)
1029 _ca
->ca_ma_value
= value
;
1031 * Validate the value of this component assertion
1033 if ( op
&& mr
->smr_syntax
->ssyn_validate( mr
->smr_syntax
, &_ca
->ca_ma_value
) != LDAP_SUCCESS
) {
1034 return LDAP_INVALID_SYNTAX
;
1038 /* componentFilterMatch contains componentFilterMatch in it */
1039 if ( strcmp(_ca
->ca_ma_rule
->smr_mrule
.mr_oid
, OID_COMP_FILTER_MATCH
) == 0) {
1041 bv
.bv_val
= cav
->cav_ptr
;
1042 bv
.bv_len
= cav_cur_len( cav
);
1043 rc
= get_comp_filter( op
, &bv
,(ComponentFilter
**)&_ca
->ca_cf
, text
);
1044 if ( rc
!= LDAP_SUCCESS
) {
1046 op
->o_tmpfree( _ca
, op
->o_tmpmemctx
);
1051 cav
->cav_ptr
= bv
.bv_val
;
1052 assert( cav
->cav_end
>= bv
.bv_val
);
1056 return LDAP_SUCCESS
;
1060 parse_comp_filter( Operation
* op
, ComponentAssertionValue
* cav
,
1061 ComponentFilter
** filt
, const char** text
)
1064 * A component filter looks like this coming in:
1065 * Filter ::= CHOICE {
1066 * item [0] ComponentAssertion,
1067 * and [1] SEQUENCE OF ComponentFilter,
1068 * or [2] SEQUENCE OF ComponentFilter,
1069 * not [3] ComponentFilter,
1076 /* TAG : item, and, or, not in RFC 4515 */
1077 tag
= strip_cav_tag( cav
);
1079 if ( tag
== LBER_ERROR
) {
1080 *text
= "error decoding comp filter";
1081 return LDAP_PROTOCOL_ERROR
;
1084 if ( tag
!= LDAP_COMP_FILTER_NOT
)
1085 strip_cav_str( cav
, "{");
1092 switch ( f
.cf_choice
) {
1093 case LDAP_COMP_FILTER_AND
:
1094 Debug( LDAP_DEBUG_FILTER
, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1095 err
= get_comp_filter_list( op
, cav
, &f
.cf_and
, text
);
1096 if ( err
!= LDAP_SUCCESS
) {
1099 if ( f
.cf_and
== NULL
) {
1100 f
.cf_choice
= SLAPD_FILTER_COMPUTED
;
1101 f
.cf_result
= LDAP_COMPARE_TRUE
;
1105 case LDAP_COMP_FILTER_OR
:
1106 Debug( LDAP_DEBUG_FILTER
, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1107 err
= get_comp_filter_list( op
, cav
, &f
.cf_or
, text
);
1108 if ( err
!= LDAP_SUCCESS
) {
1111 if ( f
.cf_or
== NULL
) {
1112 f
.cf_choice
= SLAPD_FILTER_COMPUTED
;
1113 f
.cf_result
= LDAP_COMPARE_FALSE
;
1115 /* no assert - list could be empty */
1118 case LDAP_COMP_FILTER_NOT
:
1119 Debug( LDAP_DEBUG_FILTER
, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1120 err
= parse_comp_filter( op
, cav
, &f
.cf_not
, text
);
1121 if ( err
!= LDAP_SUCCESS
) {
1125 assert( f
.cf_not
!= NULL
);
1126 if ( f
.cf_not
->cf_choice
== SLAPD_FILTER_COMPUTED
) {
1127 int fresult
= f
.cf_not
->cf_result
;
1128 f
.cf_choice
= SLAPD_FILTER_COMPUTED
;
1129 op
->o_tmpfree( f
.cf_not
, op
->o_tmpmemctx
);
1132 switch ( fresult
) {
1133 case LDAP_COMPARE_TRUE
:
1134 f
.cf_result
= LDAP_COMPARE_FALSE
;
1136 case LDAP_COMPARE_FALSE
:
1137 f
.cf_result
= LDAP_COMPARE_TRUE
;
1140 /* (!Undefined) is Undefined */
1145 case LDAP_COMP_FILTER_ITEM
:
1146 Debug( LDAP_DEBUG_FILTER
, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1147 err
= get_item( op
, cav
, &f
.cf_ca
, text
);
1148 if ( err
!= LDAP_SUCCESS
) {
1152 assert( f
.cf_ca
!= NULL
);
1156 f
.cf_choice
= SLAPD_FILTER_COMPUTED
;
1157 f
.cf_result
= SLAPD_COMPARE_UNDEFINED
;
1161 if ( err
!= LDAP_SUCCESS
&& err
!= SLAPD_DISCONNECT
) {
1162 *text
= "Component Filter Syntax Error";
1166 if ( tag
!= LDAP_COMP_FILTER_NOT
)
1167 strip_cav_str( cav
, "}");
1169 if ( err
== LDAP_SUCCESS
) {
1171 *filt
= op
->o_tmpalloc( sizeof(f
), op
->o_tmpmemctx
);
1173 *filt
= malloc( sizeof(f
) );
1182 test_comp_filter_and(
1184 ComponentSyntaxInfo
*a
,
1185 ComponentFilter
*flist
)
1188 int rtn
= LDAP_COMPARE_TRUE
;
1190 for ( f
= flist
; f
!= NULL
; f
= f
->cf_next
) {
1191 int rc
= test_comp_filter( syn
, a
, f
);
1192 if ( rc
== LDAP_COMPARE_FALSE
) {
1197 if ( rc
!= LDAP_COMPARE_TRUE
) {
1206 test_comp_filter_or(
1208 ComponentSyntaxInfo
*a
,
1209 ComponentFilter
*flist
)
1212 int rtn
= LDAP_COMPARE_TRUE
;
1214 for ( f
= flist
; f
!= NULL
; f
= f
->cf_next
) {
1215 int rc
= test_comp_filter( syn
, a
, f
);
1216 if ( rc
== LDAP_COMPARE_TRUE
) {
1221 if ( rc
!= LDAP_COMPARE_FALSE
) {
1230 csi_value_match( MatchingRule
*mr
, struct berval
* bv_attr
,
1231 struct berval
* bv_assert
)
1236 assert( mr
!= NULL
);
1237 assert( !(mr
->smr_usage
& SLAP_MR_COMPONENT
) );
1239 if( !mr
->smr_match
) return LDAP_INAPPROPRIATE_MATCHING
;
1241 rc
= (mr
->smr_match
)( &match
, 0, NULL
/*ad->ad_type->sat_syntax*/,
1242 mr
, bv_attr
, bv_assert
);
1244 if ( rc
!= LDAP_SUCCESS
) return rc
;
1246 return match
? LDAP_COMPARE_FALSE
: LDAP_COMPARE_TRUE
;
1250 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1253 test_comp_filter_item(
1255 ComponentSyntaxInfo
*csi_attr
,
1256 ComponentAssertion
*ca
)
1259 void *attr_nm
, *assert_nm
;
1261 if ( strcmp(ca
->ca_ma_rule
->smr_mrule
.mr_oid
,
1262 OID_COMP_FILTER_MATCH
) == 0 && ca
->ca_cf
) {
1263 /* componentFilterMatch inside of componentFilterMatch */
1264 rc
= test_comp_filter( syn
, csi_attr
, ca
->ca_cf
);
1268 /* Memory for storing will-be-extracted attribute values */
1269 attr_nm
= nibble_mem_allocator ( 1024*4 , 1024 );
1270 if ( !attr_nm
) return LDAP_PROTOCOL_ERROR
;
1272 /* Memory for storing component assertion values */
1273 if( !ca
->ca_comp_data
.cd_mem_op
) {
1274 assert_nm
= nibble_mem_allocator ( 256, 64 );
1276 nibble_mem_free ( attr_nm
);
1277 return LDAP_PROTOCOL_ERROR
;
1279 ca
->ca_comp_data
.cd_mem_op
= assert_nm
;
1282 assert_nm
= ca
->ca_comp_data
.cd_mem_op
;
1285 /* component reference initialization */
1286 if ( ca
->ca_comp_ref
) {
1287 ca
->ca_comp_ref
->cr_curr
= ca
->ca_comp_ref
->cr_list
;
1289 rc
= test_components( attr_nm
, assert_nm
, csi_attr
, ca
);
1291 /* free memory used for storing extracted attribute value */
1292 nibble_mem_free ( attr_nm
);
1299 ComponentSyntaxInfo
*a
,
1300 ComponentFilter
*f
)
1304 if ( !f
) return LDAP_PROTOCOL_ERROR
;
1306 Debug( LDAP_DEBUG_FILTER
, "test_comp_filter\n", 0, 0, 0 );
1307 switch ( f
->cf_choice
) {
1308 case SLAPD_FILTER_COMPUTED
:
1311 case LDAP_COMP_FILTER_AND
:
1312 rc
= test_comp_filter_and( syn
, a
, f
->cf_and
);
1314 case LDAP_COMP_FILTER_OR
:
1315 rc
= test_comp_filter_or( syn
, a
, f
->cf_or
);
1317 case LDAP_COMP_FILTER_NOT
:
1318 rc
= test_comp_filter( syn
, a
, f
->cf_not
);
1321 case LDAP_COMPARE_TRUE
:
1322 rc
= LDAP_COMPARE_FALSE
;
1324 case LDAP_COMPARE_FALSE
:
1325 rc
= LDAP_COMPARE_TRUE
;
1329 case LDAP_COMP_FILTER_ITEM
:
1330 rc
= test_comp_filter_item( syn
, a
, f
->cf_ca
);
1333 rc
= LDAP_PROTOCOL_ERROR
;
1340 free_comp_filter_list( ComponentFilter
* f
)
1342 ComponentFilter
* tmp
;
1343 for ( tmp
= f
; tmp
; tmp
= tmp
->cf_next
) {
1344 free_comp_filter( tmp
);
1349 free_comp_filter( ComponentFilter
* f
)
1352 Debug( LDAP_DEBUG_FILTER
,
1353 "free_comp_filter: Invalid filter so failed to release memory\n",
1357 switch ( f
->cf_choice
) {
1358 case LDAP_COMP_FILTER_AND
:
1359 case LDAP_COMP_FILTER_OR
:
1360 free_comp_filter_list( f
->cf_any
);
1362 case LDAP_COMP_FILTER_NOT
:
1363 free_comp_filter( f
->cf_any
);
1365 case LDAP_COMP_FILTER_ITEM
:
1366 if ( nibble_mem_free
&& f
->cf_ca
->ca_comp_data
.cd_mem_op
) {
1367 nibble_mem_free( f
->cf_ca
->ca_comp_data
.cd_mem_op
);
1376 component_free( ComponentFilter
*f
) {
1377 free_comp_filter( f
);
1381 free_ComponentData( Attribute
*a
) {
1382 if ( a
->a_comp_data
->cd_mem_op
)
1383 component_destructor( a
->a_comp_data
->cd_mem_op
);
1384 free ( a
->a_comp_data
);
1385 a
->a_comp_data
= NULL
;