1 /* component.c -- Component Filter Match Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2004 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, Attribute *a, struct berval *bv,
69 componentCertificateValidate(
77 componentFilterValidate(
85 allComponentsValidate(
93 componentFilterMatch (
101 Attribute *a = (Attribute*)value;
102 MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
106 if ( !(mr && mr->smr_usage & SLAP_MR_COMPONENT) || !ma->ma_cf )
107 return LDAP_INAPPROPRIATE_MATCHING;
109 rc = test_comp_filter( syntax, a, a->a_vals, ma->ma_cf );
111 if ( rc == LDAP_COMPARE_TRUE ) {
115 else if ( rc == LDAP_COMPARE_FALSE ) {
120 return LDAP_INAPPROPRIATE_MATCHING;
125 directoryComponentsMatch(
130 struct berval *value,
131 void *assertedValue )
133 /* Only for Registeration */
144 struct berval *value,
145 void *assertedValue )
147 /* Only for Registeration */
153 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 )
167 ComponentReference* dup_cr;
168 ComponentId* ci_curr;
169 ComponentId** ci_temp;
172 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
174 dup_cr->cr_len = cr->cr_len;
175 dup_cr->cr_string = cr->cr_string;
177 ci_temp = &dup_cr->cr_list;
178 ci_curr = cr->cr_list;
180 for ( ; ci_curr ; 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 )
233 ComponentAssertion* ca;
236 if ( !in_ca->ca_comp_ref )
237 return SLAPD_DISCONNECT;
239 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
241 return LDAP_NO_MEMORY;
243 (*out_ca)->ca_comp_data.cd_tree = NULL;
244 (*out_ca)->ca_comp_data.cd_mem_op = NULL;
246 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
247 (*out_ca)->ca_use_def = 0;
248 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
250 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
251 len = get_len_of_next_assert_value ( assert_bv, '$' );
253 return SLAPD_DISCONNECT;
254 (*out_ca)->ca_ma_value.bv_len = len;
263 ComponentFilter *in_f,
264 ComponentFilter **out_f )
267 ComponentFilter dup_f = {0};
269 if ( !in_f ) return LDAP_PROTOCOL_ERROR;
271 switch ( in_f->cf_choice ) {
272 case LDAP_COMP_FILTER_AND:
273 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
274 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
276 case LDAP_COMP_FILTER_OR:
277 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
278 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
280 case LDAP_COMP_FILTER_NOT:
281 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
282 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
284 case LDAP_COMP_FILTER_ITEM:
285 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
286 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
289 rc = LDAP_PROTOCOL_ERROR;
292 if ( rc == LDAP_SUCCESS ) {
293 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
302 get_aliased_filter ( Operation* op, MatchingRuleAssertion* ma, AttributeAliasing* aa, const char** text )
305 struct berval assert_bv;
306 ComponentAssertion* ca;
308 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
310 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR;
312 assert_bv = ma->ma_value;
313 /* Attribute Description is replaced with aliased one */
314 ma->ma_desc = aa->aa_aliased_ad;
315 ma->ma_rule = aa->aa_mr;
317 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
318 * the component assertion value in assert_bv
319 * Multiple values may be separated with '$'
321 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
325 get_comp_filter( Operation* op, struct berval* bv, ComponentFilter** filt,
328 ComponentAssertionValue cav;
331 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
332 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
335 rc = parse_comp_filter( op, &cav, filt, text );
336 bv->bv_val = cav.cav_ptr;
342 eat_whsp( ComponentAssertionValue* cav )
344 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
350 cav_cur_len( ComponentAssertionValue* cav )
352 return cav->cav_end - cav->cav_ptr;
356 comp_first_element( ComponentAssertionValue* cav )
359 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
360 return LDAP_COMP_FILTER_ITEM;
362 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
363 return LDAP_COMP_FILTER_AND;
365 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
366 return LDAP_COMP_FILTER_OR;
368 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
369 return LDAP_COMP_FILTER_NOT;
372 return LDAP_COMP_FILTER_UNDEFINED;
376 comp_next_element( ComponentAssertionValue* cav )
380 if ( *(cav->cav_ptr) == ',' ) {
381 /* move pointer to the next CA */
383 return comp_first_element( cav );
385 else return LDAP_COMP_FILTER_UNDEFINED;
389 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
390 ComponentFilter** f, const char** text )
392 ComponentFilter **new;
396 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
398 for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
399 tag = comp_next_element( cav ) )
401 err = parse_comp_filter( op, cav, new, text );
402 if ( err != LDAP_SUCCESS )
404 new = &(*new)->cf_next;
408 return( LDAP_SUCCESS );
412 get_componentId( Operation *op, ComponentAssertionValue* cav,
413 ComponentId ** cid, const char** text )
419 type = peek_componentId_type( cav );
421 Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
426 case LDAP_COMPREF_IDENTIFIER :
427 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
428 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
429 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
430 _cid.ci_val.ci_identifier.bv_len = len;
433 case LDAP_COMPREF_FROM_BEGINNING :
434 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
435 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
436 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
439 case LDAP_COMPREF_FROM_END :
440 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
441 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
442 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
445 case LDAP_COMPREF_COUNT :
446 _cid.ci_val.ci_count = 0;
449 case LDAP_COMPREF_CONTENT :
450 _cid.ci_val.ci_content = 1;
451 cav->cav_ptr += strlen("content");
453 case LDAP_COMPREF_SELECT :
454 if ( cav->cav_ptr[len] != '(' )
455 return LDAP_COMPREF_UNDEFINED;
456 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
457 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
459 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
460 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
461 cav->cav_ptr += len + 1;
463 case LDAP_COMPREF_ALL :
464 _cid.ci_val.ci_all = '*';
468 return LDAP_COMPREF_UNDEFINED;
472 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
474 *cid = malloc( sizeof( ComponentId ) );
480 peek_componentId_type( ComponentAssertionValue* cav )
483 if ( cav->cav_ptr[0] == '-' )
484 return LDAP_COMPREF_FROM_END;
485 else if ( cav->cav_ptr[0] == '(' )
486 return LDAP_COMPREF_SELECT;
487 else if ( cav->cav_ptr[0] == '*' )
488 return LDAP_COMPREF_ALL;
489 else if ( cav->cav_ptr[0] == '0' )
490 return LDAP_COMPREF_COUNT;
491 else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
492 return LDAP_COMPREF_FROM_BEGINNING;
493 else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
494 strncmp(cav->cav_ptr,"content",7) == 0 )
495 return LDAP_COMPREF_CONTENT;
496 else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
497 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
499 return LDAP_COMPREF_IDENTIFIER;
501 return LDAP_COMPREF_UNDEFINED;
505 comp_next_id( ComponentAssertionValue* cav )
508 if ( *(cav->cav_ptr) == '.' ) {
510 return LDAP_COMPREF_DEFINED;
512 else return LDAP_COMPREF_UNDEFINED;
518 get_component_reference( Operation *op, ComponentAssertionValue* cav,
519 ComponentReference** cr, const char** text )
523 ComponentReference* ca_comp_ref;
524 ComponentId** cr_list;
529 start = cav->cav_ptr;
530 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS )
533 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
535 ca_comp_ref = malloc( sizeof( ComponentReference ) );
537 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
539 cr_list = &ca_comp_ref->cr_list;
541 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
542 ; type = comp_next_id( cav ), count++ ) {
543 rc = get_componentId( op, cav, cr_list, text );
544 if ( rc == LDAP_SUCCESS ) {
545 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
546 cr_list = &(*cr_list)->ci_next;
548 else if ( rc == LDAP_COMPREF_UNDEFINED )
551 ca_comp_ref->cr_len = count;
553 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
555 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
561 if ( rc == LDAP_SUCCESS ) {
566 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
568 free( ca_comp_ref ) ;
570 (*cr)->cr_string.bv_val = start;
571 (*cr)->cr_string.bv_len = end - start + 1;
577 insert_component_reference( ComponentReference *cr, ComponentReference** cr_list) {
579 return LDAP_PARAM_ERROR;
584 cr->cr_next = *cr_list;
591 * If there is '.' in the name of a given attribute
592 * the first '.'- following characters are considered
593 * as a component reference of the attribute
594 * EX) userCertificate.toBeSigned.serialNumber
595 * attribute : userCertificate
596 * component reference : toBeSigned.serialNumber
599 is_component_reference( char* attr ) {
601 for ( i=0; attr[i] != '\0' ; i++ ) {
602 if ( attr[i] == '.' )
609 extract_component_reference( char* attr, ComponentReference** cr ) {
613 ComponentAssertionValue cav;
616 for ( i=0; attr[i] != '\0' ; i++ ) {
617 if ( attr[i] == '.' ) break;
621 return LDAP_PARAM_ERROR;
624 cr_ptr = attr + i + 1 ;
625 cr_len = strlen ( cr_ptr );
627 return LDAP_PARAM_ERROR;
629 /* enclosed between double quotes*/
630 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
631 memcpy( cav.cav_buf+1, cr_ptr, cr_len );
632 cav.cav_buf[0] = '"';
633 cav.cav_buf[cr_len+1] = '"';
634 cav.cav_end = cr_ptr + cr_len + 2;
636 rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
637 if ( rc != LDAP_SUCCESS )
639 (*cr)->cr_string.bv_val = cav.cav_buf;
640 (*cr)->cr_string.bv_len = cr_len + 2;
645 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
646 int* ca_use_def, const char** text )
648 strip_cav_str( cav, "useDefaultValues" );
649 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
650 strip_cav_str( cav, "TRUE" );
652 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
653 strip_cav_str( cav, "FALSE" );
656 return LDAP_INVALID_SYNTAX;
663 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
664 MatchingRule** mr, const char** text )
667 struct berval rule_text = { 0L, NULL };
671 for ( ; ; count++ ) {
672 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
673 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
674 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
679 *text = "component matching rule not recognized";
680 return LDAP_INAPPROPRIATE_MATCHING;
683 rule_text.bv_len = count;
684 rule_text.bv_val = cav->cav_ptr;
685 *mr = mr_bvfind( &rule_text );
686 cav->cav_ptr += count;
687 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
689 *text = "component matching rule not recognized";
690 return LDAP_INAPPROPRIATE_MATCHING;
696 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
698 int count, sequent_dquote, unclosed_brace, succeed;
702 * Four cases of GSER <Values>
704 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
705 * 2) '...'B or '...'H :
706 * BitStringVal, OctetStringVal
708 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
709 * 4) Between two white spaces
710 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
714 if ( cav->cav_ptr[0] == '"' ) {
715 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
716 /* In order to find escaped double quote */
717 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
718 else sequent_dquote = 0;
720 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
724 if ( ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') ||
725 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
731 if ( !succeed || cav->cav_ptr[count] != '"' )
732 return LDAP_FILTER_ERROR;
734 bv->bv_val = cav->cav_ptr + 1;
735 bv->bv_len = count - 1; /* exclude '"' */
737 else if ( cav->cav_ptr[0] == '\'' ) {
738 for( count = 1 ; ; count++ ) {
739 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
742 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B')||
743 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) {
749 if ( !succeed || !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
750 return LDAP_FILTER_ERROR;
752 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
753 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
756 else if ( cav->cav_ptr[0] == '{' ) {
757 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
758 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
759 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
761 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end )
763 if ( unclosed_brace == 0 ) {
769 if ( !succeed || cav->cav_ptr[count] != '}' )
770 return LDAP_FILTER_ERROR;
772 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
773 bv->bv_len = count - 1;/* exclude "'B" */
777 /*Find following white space where the value is ended*/
778 for( count = 1 ; ; count++ ) {
779 if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '{' || (cav->cav_ptr+count) > cav->cav_end ) {
783 bv->bv_val = cav->cav_ptr;
787 cav->cav_ptr += bv->bv_len;
793 get_matching_value( Operation *op, ComponentAssertion* ca,
794 ComponentAssertionValue* cav, struct berval* bv,
797 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
798 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
799 return LDAP_FILTER_ERROR;
803 /* embeded componentFilterMatch Description */
804 bv->bv_val = cav->cav_ptr;
805 bv->bv_len = cav_cur_len( cav );
811 /* Don't move the position pointer, just peek given string */
813 peek_cav_str( ComponentAssertionValue* cav, char* str )
816 if ( cav_cur_len( cav ) >= strlen( str ) &&
817 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
820 return LDAP_INVALID_SYNTAX;
824 strip_cav_str( ComponentAssertionValue* cav, char* str)
827 if ( cav_cur_len( cav ) >= strlen( str ) &&
828 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
829 cav->cav_ptr += strlen( str );
833 return LDAP_INVALID_SYNTAX;
837 * TAG : "item", "and", "or", "not"
840 strip_cav_tag( ComponentAssertionValue* cav )
844 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
845 strip_cav_str( cav , "item:" );
846 return LDAP_COMP_FILTER_ITEM;
848 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
849 strip_cav_str( cav , "and:" );
850 return LDAP_COMP_FILTER_AND;
852 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
853 strip_cav_str( cav , "or:" );
854 return LDAP_COMP_FILTER_OR;
856 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
857 strip_cav_str( cav , "not:" );
858 return LDAP_COMP_FILTER_NOT;
865 * when encoding, "item" is denotation of ComponentAssertion
866 * ComponentAssertion :: SEQUENCE {
867 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
868 * useDefaultValues BOOLEAN DEFAULT TRUE,
869 * rule MATCHING-RULE.&id,
870 * value MATCHING-RULE.&AssertionType }
873 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
877 ComponentAssertion* _ca;
882 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
884 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
886 _ca = malloc( sizeof( ComponentAssertion ) );
888 if ( !_ca ) return LDAP_NO_MEMORY;
890 _ca->ca_comp_data.cd_tree = NULL;
891 _ca->ca_comp_data.cd_mem_op = NULL;
893 rc = peek_cav_str( cav, "component" );
894 if ( rc == LDAP_SUCCESS ) {
895 strip_cav_str( cav, "component" );
896 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
897 if ( rc != LDAP_SUCCESS ) {
899 op->o_tmpfree( _ca, op->o_tmpmemctx );
902 return LDAP_INVALID_SYNTAX;
904 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
907 _ca->ca_comp_ref = NULL;
910 rc = peek_cav_str( cav, "useDefaultValues");
911 if ( rc == LDAP_SUCCESS ) {
912 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
913 if ( rc != LDAP_SUCCESS ) {
915 op->o_tmpfree( _ca, op->o_tmpmemctx );
918 return LDAP_INVALID_SYNTAX;
920 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
923 else _ca->ca_use_def = 1;
925 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
926 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
928 op->o_tmpfree( _ca, op->o_tmpmemctx );
931 return LDAP_INAPPROPRIATE_MATCHING;
934 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
936 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
937 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
939 op->o_tmpfree( _ca, op->o_tmpmemctx );
942 return LDAP_INVALID_SYNTAX;
946 * Normalize the value of this component assertion when the matching
947 * rule is one of existing matching rules
949 mr = _ca->ca_ma_rule;
950 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
952 value.bv_val[value.bv_len] = '\0';
953 rc = mr->smr_normalize (
954 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
956 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
957 if ( rc != LDAP_SUCCESS )
961 _ca->ca_ma_value = value;
963 * Validate the value of this component assertion
965 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
966 return LDAP_INVALID_SYNTAX;
970 /* componentFilterMatch contains componentFilterMatch in it */
971 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
973 bv.bv_val = cav->cav_ptr;
974 bv.bv_len = cav_cur_len( cav );
975 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
976 if ( rc != LDAP_SUCCESS ) {
978 op->o_tmpfree( _ca, op->o_tmpmemctx );
983 cav->cav_ptr = bv.bv_val;
984 assert( cav->cav_end >= bv.bv_val );
992 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
993 ComponentFilter** filt, const char** text )
996 * A component filter looks like this coming in:
997 * Filter ::= CHOICE {
998 * item [0] ComponentAssertion,
999 * and [1] SEQUENCE OF ComponentFilter,
1000 * or [2] SEQUENCE OF ComponentFilter,
1001 * not [3] ComponentFilter,
1008 /* TAG : item, and, or, not in RFC 2254 */
1009 tag = strip_cav_tag( cav );
1011 if ( tag == LBER_ERROR ) {
1012 *text = "error decoding comp filter";
1013 return LDAP_PROTOCOL_ERROR;
1016 if ( tag != LDAP_COMP_FILTER_NOT )
1017 strip_cav_str( cav, "{");
1024 switch ( f.cf_choice ) {
1025 case LDAP_COMP_FILTER_AND:
1026 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1027 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1028 if ( err != LDAP_SUCCESS ) {
1031 if ( f.cf_and == NULL ) {
1032 f.cf_choice = SLAPD_FILTER_COMPUTED;
1033 f.cf_result = LDAP_COMPARE_TRUE;
1037 case LDAP_COMP_FILTER_OR:
1038 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1039 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1040 if ( err != LDAP_SUCCESS ) {
1043 if ( f.cf_or == NULL ) {
1044 f.cf_choice = SLAPD_FILTER_COMPUTED;
1045 f.cf_result = LDAP_COMPARE_FALSE;
1047 /* no assert - list could be empty */
1050 case LDAP_COMP_FILTER_NOT:
1051 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1052 err = parse_comp_filter( op, cav, &f.cf_not, text );
1053 if ( err != LDAP_SUCCESS ) {
1057 assert( f.cf_not != NULL );
1058 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1059 int fresult = f.cf_not->cf_result;
1060 f.cf_choice = SLAPD_FILTER_COMPUTED;
1061 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1064 switch ( fresult ) {
1065 case LDAP_COMPARE_TRUE:
1066 f.cf_result = LDAP_COMPARE_FALSE;
1068 case LDAP_COMPARE_FALSE:
1069 f.cf_result = LDAP_COMPARE_TRUE;
1072 /* (!Undefined) is Undefined */
1077 case LDAP_COMP_FILTER_ITEM:
1078 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1079 err = get_item( op, cav, &f.cf_ca, text );
1080 if ( err != LDAP_SUCCESS ) {
1084 assert( f.cf_ca != NULL );
1088 f.cf_choice = SLAPD_FILTER_COMPUTED;
1089 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1093 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1094 *text = "Component Filter Syntax Error";
1098 if ( tag != LDAP_COMP_FILTER_NOT )
1099 strip_cav_str( cav, "}");
1101 if ( err == LDAP_SUCCESS ) {
1103 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1105 *filt = malloc( sizeof(f) );
1114 test_comp_filter_and(
1118 ComponentFilter *flist )
1121 int rtn = LDAP_COMPARE_TRUE;
1123 for ( f = flist ; f != NULL; f = f->cf_next ) {
1124 int rc = test_comp_filter( syn, a, bv, f );
1125 if ( rc == LDAP_COMPARE_FALSE ) {
1130 if ( rc != LDAP_COMPARE_TRUE ) {
1139 test_comp_filter_or(
1143 ComponentFilter *flist )
1146 int rtn = LDAP_COMPARE_TRUE;
1148 for ( f = flist ; f != NULL; f = f->cf_next ) {
1149 int rc = test_comp_filter( syn, a, bv, f );
1150 if ( rc == LDAP_COMPARE_TRUE ) {
1155 if ( rc != LDAP_COMPARE_FALSE ) {
1164 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1165 struct berval* bv_assert )
1170 assert( mr != NULL );
1171 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1173 if( !mr->smr_match ) {
1174 return LDAP_INAPPROPRIATE_MATCHING;
1177 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1178 mr, bv_attr, bv_assert );
1179 if ( rc == LDAP_SUCCESS )
1180 return match? LDAP_COMPARE_FALSE:LDAP_COMPARE_TRUE;
1186 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1189 test_comp_filter_item(
1193 ComponentAssertion *ca )
1196 ComponentSyntaxInfo* csi_attr, *csi_assert=NULL;
1197 void *attr_nm, *assert_nm;
1199 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1200 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1201 /* componentFilterMatch inside of componentFilterMatch */
1202 rc = test_comp_filter( syn, a, bv, ca->ca_cf );
1206 /* load attribute containg components */
1207 if ( !a->a_comp_data && attr_converter && nibble_mem_allocator ) {
1208 a->a_comp_data = malloc( sizeof( ComponentData ) );
1209 /* Memory chunk pre-allocation for decoders */
1210 a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*16, 1024 );
1211 a->a_comp_data->cd_tree = attr_converter (a, syn, bv);
1214 if ( a->a_comp_data->cd_tree == NULL ) {
1215 nibble_mem_free( a->a_comp_data->cd_mem_op );
1216 free ( a->a_comp_data );
1217 a->a_comp_data = NULL;
1218 return LDAP_PROTOCOL_ERROR;
1221 /* Memory for storing will-be-extracted attribute values */
1222 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1223 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1225 /* Memory for storing component assertion values */
1226 if( !ca->ca_comp_data.cd_mem_op ) {
1227 assert_nm = nibble_mem_allocator ( 256, 64 );
1229 nibble_mem_free ( attr_nm );
1230 return LDAP_PROTOCOL_ERROR;
1232 ca->ca_comp_data.cd_mem_op = assert_nm;
1235 assert_nm = ca->ca_comp_data.cd_mem_op;
1238 /* component reference initialization */
1239 if ( ca->ca_comp_ref )
1240 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1241 rc = test_components( attr_nm, assert_nm, (ComponentSyntaxInfo*)a->a_comp_data->cd_tree, ca );
1243 /* free memory used for storing extracted attribute value */
1244 nibble_mem_free ( attr_nm );
1253 ComponentFilter *f )
1257 if ( !f ) return LDAP_PROTOCOL_ERROR;
1259 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1260 switch ( f->cf_choice ) {
1261 case SLAPD_FILTER_COMPUTED:
1264 case LDAP_COMP_FILTER_AND:
1265 rc = test_comp_filter_and( syn, a, bv, f->cf_and );
1267 case LDAP_COMP_FILTER_OR:
1268 rc = test_comp_filter_or( syn, a, bv, f->cf_or );
1270 case LDAP_COMP_FILTER_NOT:
1271 rc = test_comp_filter( syn, a, bv, f->cf_not );
1274 case LDAP_COMPARE_TRUE:
1275 rc = LDAP_COMPARE_FALSE;
1277 case LDAP_COMPARE_FALSE:
1278 rc = LDAP_COMPARE_TRUE;
1282 case LDAP_COMP_FILTER_ITEM:
1283 rc = test_comp_filter_item( syn, a, bv, f->cf_ca );
1286 rc = LDAP_PROTOCOL_ERROR;
1293 free_comp_filter_list( ComponentFilter* f )
1295 ComponentFilter* tmp;
1296 for ( tmp = f; tmp; tmp = tmp->cf_next )
1298 free_comp_filter( tmp );
1303 free_comp_filter( ComponentFilter* f )
1306 Debug( LDAP_DEBUG_FILTER, "free_comp_filter:Invalid filter so failed to release memory\n", 0, 0, 0 );
1309 switch ( f->cf_choice ) {
1310 case LDAP_COMP_FILTER_AND:
1311 case LDAP_COMP_FILTER_OR:
1312 free_comp_filter_list( f->cf_any );
1314 case LDAP_COMP_FILTER_NOT:
1315 free_comp_filter( f->cf_any );
1317 case LDAP_COMP_FILTER_ITEM:
1318 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op )
1319 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1328 component_free( ComponentFilter *f ) {
1329 free_comp_filter( f );