1 /* component.c -- Component Filter Match Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2005 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 )
159 cav->cav_ptr = cav->cav_buf = bv->bv_val;
160 cav->cav_end = bv->bv_val + bv->bv_len;
166 dup_comp_ref ( Operation* op, ComponentReference* cr )
169 ComponentReference* dup_cr;
170 ComponentId* ci_curr;
171 ComponentId** ci_temp;
174 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
176 dup_cr->cr_len = cr->cr_len;
177 dup_cr->cr_string = cr->cr_string;
179 ci_temp = &dup_cr->cr_list;
180 ci_curr = cr->cr_list;
182 for ( ; ci_curr != NULL ;
183 ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next )
185 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
186 if ( !ci_temp ) return NULL;
187 **ci_temp = *ci_curr;
190 dup_cr->cr_curr = dup_cr->cr_list;
196 dup_comp_filter_list (
199 ComponentFilter* in_f,
200 ComponentFilter** out_f )
202 ComponentFilter **new, *f;
206 for ( f = in_f; f != NULL; f = f->cf_next ) {
207 rc = dup_comp_filter( op, bv, f, new );
208 if ( rc != LDAP_SUCCESS ) {
211 new = &(*new)->cf_next;
217 get_len_of_next_assert_value ( struct berval* bv, char separator )
221 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
225 bv->bv_val += (i + 1);
226 bv->bv_len -= (i + 1);
231 dup_comp_filter_item (
233 struct berval* assert_bv,
234 ComponentAssertion* in_ca,
235 ComponentAssertion** out_ca )
237 ComponentAssertion* ca;
240 if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT;
242 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
243 if ( !(*out_ca) ) return LDAP_NO_MEMORY;
245 (*out_ca)->ca_comp_data.cd_tree = NULL;
246 (*out_ca)->ca_comp_data.cd_mem_op = NULL;
248 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
249 (*out_ca)->ca_use_def = 0;
250 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
252 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
253 len = get_len_of_next_assert_value ( assert_bv, '$' );
254 if ( len <= 0 ) return SLAPD_DISCONNECT;
255 (*out_ca)->ca_ma_value.bv_len = len;
264 ComponentFilter *in_f,
265 ComponentFilter **out_f )
268 ComponentFilter dup_f = {0};
270 if ( !in_f ) return LDAP_PROTOCOL_ERROR;
272 switch ( in_f->cf_choice ) {
273 case LDAP_COMP_FILTER_AND:
274 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
275 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
277 case LDAP_COMP_FILTER_OR:
278 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
279 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
281 case LDAP_COMP_FILTER_NOT:
282 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
283 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
285 case LDAP_COMP_FILTER_ITEM:
286 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
287 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
290 rc = LDAP_PROTOCOL_ERROR;
293 if ( rc == LDAP_SUCCESS ) {
294 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
302 get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, 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 );
311 return LDAP_PROTOCOL_ERROR;
313 assert_bv = a_assert->aa_value;
315 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
316 * the component assertion value in assert_bv
317 * Multiple values may be separated with '$'
319 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf );
323 get_aliased_filter( Operation* op,
324 MatchingRuleAssertion* ma, AttributeAliasing* aa,
328 struct berval assert_bv;
329 ComponentAssertion* ca;
331 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
333 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR;
335 assert_bv = ma->ma_value;
336 /* Attribute Description is replaced with aliased one */
337 ma->ma_desc = aa->aa_aliased_ad;
338 ma->ma_rule = aa->aa_mr;
340 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
341 * the component assertion value in assert_bv
342 * Multiple values may be separated with '$'
344 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
348 get_comp_filter( Operation* op, struct berval* bv,
349 ComponentFilter** filt, const char **text )
351 ComponentAssertionValue cav;
354 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
355 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
358 rc = parse_comp_filter( op, &cav, filt, text );
359 bv->bv_val = cav.cav_ptr;
365 eat_whsp( ComponentAssertionValue* cav )
367 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
373 cav_cur_len( ComponentAssertionValue* cav )
375 return cav->cav_end - cav->cav_ptr;
379 comp_first_element( ComponentAssertionValue* cav )
382 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
383 return LDAP_COMP_FILTER_ITEM;
385 } else if ( cav_cur_len( cav ) >= 7 &&
386 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
388 return LDAP_COMP_FILTER_AND;
390 } else if ( cav_cur_len( cav ) >= 6 &&
391 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
393 return LDAP_COMP_FILTER_OR;
395 } else if ( cav_cur_len( cav ) >= 7 &&
396 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
398 return LDAP_COMP_FILTER_NOT;
401 return LDAP_COMP_FILTER_UNDEFINED;
406 comp_next_element( ComponentAssertionValue* cav )
409 if ( *(cav->cav_ptr) == ',' ) {
410 /* move pointer to the next CA */
412 return comp_first_element( cav );
414 else return LDAP_COMP_FILTER_UNDEFINED;
418 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
419 ComponentFilter** f, const char** text )
421 ComponentFilter **new;
425 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
427 for ( tag = comp_first_element( cav );
428 tag != LDAP_COMP_FILTER_UNDEFINED;
429 tag = comp_next_element( cav ) )
431 err = parse_comp_filter( op, cav, new, text );
432 if ( err != LDAP_SUCCESS ) return ( err );
433 new = &(*new)->cf_next;
437 return( LDAP_SUCCESS );
441 get_componentId( Operation *op, ComponentAssertionValue* cav,
442 ComponentId ** cid, const char** text )
448 type = peek_componentId_type( cav );
450 Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
451 (unsigned long) type, 0, 0 );
456 case LDAP_COMPREF_IDENTIFIER :
457 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
458 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
459 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
460 _cid.ci_val.ci_identifier.bv_len = len;
463 case LDAP_COMPREF_FROM_BEGINNING :
464 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
465 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
466 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
469 case LDAP_COMPREF_FROM_END :
470 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
471 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
472 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
475 case LDAP_COMPREF_COUNT :
476 _cid.ci_val.ci_count = 0;
479 case LDAP_COMPREF_CONTENT :
480 _cid.ci_val.ci_content = 1;
481 cav->cav_ptr += strlen("content");
483 case LDAP_COMPREF_SELECT :
484 if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
485 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
486 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
488 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
489 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
490 cav->cav_ptr += len + 1;
492 case LDAP_COMPREF_ALL :
493 _cid.ci_val.ci_all = '*';
497 return LDAP_COMPREF_UNDEFINED;
501 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
503 *cid = malloc( sizeof( ComponentId ) );
510 peek_componentId_type( ComponentAssertionValue* cav )
514 if ( cav->cav_ptr[0] == '-' ) {
515 return LDAP_COMPREF_FROM_END;
517 } else if ( cav->cav_ptr[0] == '(' ) {
518 return LDAP_COMPREF_SELECT;
520 } else if ( cav->cav_ptr[0] == '*' ) {
521 return LDAP_COMPREF_ALL;
523 } else if ( cav->cav_ptr[0] == '0' ) {
524 return LDAP_COMPREF_COUNT;
526 } else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
527 return LDAP_COMPREF_FROM_BEGINNING;
529 } else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
530 strncmp(cav->cav_ptr,"content",7) == 0 )
532 return LDAP_COMPREF_CONTENT;
533 } else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
534 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
536 return LDAP_COMPREF_IDENTIFIER;
539 return LDAP_COMPREF_UNDEFINED;
543 comp_next_id( ComponentAssertionValue* cav )
545 if ( *(cav->cav_ptr) == '.' ) {
547 return LDAP_COMPREF_DEFINED;
550 return LDAP_COMPREF_UNDEFINED;
556 get_component_reference(
558 ComponentAssertionValue* cav,
559 ComponentReference** cr,
564 ComponentReference* ca_comp_ref;
565 ComponentId** cr_list;
570 start = cav->cav_ptr;
571 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
573 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
576 ca_comp_ref = malloc( sizeof( ComponentReference ) );
579 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
581 cr_list = &ca_comp_ref->cr_list;
583 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
584 ; type = comp_next_id( cav ), count++ )
586 rc = get_componentId( op, cav, cr_list, text );
587 if ( rc == LDAP_SUCCESS ) {
588 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
589 cr_list = &(*cr_list)->ci_next;
591 } else if ( rc == LDAP_COMPREF_UNDEFINED ) {
595 ca_comp_ref->cr_len = count;
597 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
599 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
606 if ( rc == LDAP_SUCCESS ) {
611 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
614 free( ca_comp_ref ) ;
617 (*cr)->cr_string.bv_val = start;
618 (*cr)->cr_string.bv_len = end - start + 1;
624 insert_component_reference(
625 ComponentReference *cr,
626 ComponentReference** cr_list)
628 if ( !cr ) return LDAP_PARAM_ERROR;
634 cr->cr_next = *cr_list;
641 * If there is '.' in the name of a given attribute
642 * the first '.'- following characters are considered
643 * as a component reference of the attribute
644 * EX) userCertificate.toBeSigned.serialNumber
645 * attribute : userCertificate
646 * component reference : toBeSigned.serialNumber
649 is_component_reference( char* attr ) {
651 for ( i=0; attr[i] != '\0' ; i++ ) {
652 if ( attr[i] == '.' ) return (1);
658 extract_component_reference(
660 ComponentReference** cr )
665 ComponentAssertionValue cav;
668 for ( i=0; attr[i] != '\0' ; i++ ) {
669 if ( attr[i] == '.' ) break;
672 if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
675 cr_ptr = attr + i + 1 ;
676 cr_len = strlen ( cr_ptr );
677 if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
679 /* enclosed between double quotes*/
680 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
681 memcpy( cav.cav_buf+1, cr_ptr, cr_len );
682 cav.cav_buf[0] = '"';
683 cav.cav_buf[cr_len+1] = '"';
684 cav.cav_end = cr_ptr + cr_len + 2;
686 rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
687 if ( rc != LDAP_SUCCESS ) return rc;
688 (*cr)->cr_string.bv_val = cav.cav_buf;
689 (*cr)->cr_string.bv_len = cr_len + 2;
695 get_ca_use_default( Operation *op,
696 ComponentAssertionValue* cav,
697 int* ca_use_def, const char** text )
699 strip_cav_str( cav, "useDefaultValues" );
701 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
702 strip_cav_str( cav, "TRUE" );
705 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
706 strip_cav_str( cav, "FALSE" );
710 return LDAP_INVALID_SYNTAX;
717 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
718 MatchingRule** mr, const char** text )
721 struct berval rule_text = { 0L, NULL };
725 for ( ; ; count++ ) {
726 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
727 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
728 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
735 *text = "component matching rule not recognized";
736 return LDAP_INAPPROPRIATE_MATCHING;
739 rule_text.bv_len = count;
740 rule_text.bv_val = cav->cav_ptr;
741 *mr = mr_bvfind( &rule_text );
742 cav->cav_ptr += count;
743 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
744 (*mr)->smr_mrule.mr_oid, 0, 0 );
746 *text = "component matching rule not recognized";
747 return LDAP_INAPPROPRIATE_MATCHING;
753 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
755 int count, sequent_dquote, unclosed_brace, succeed;
759 * Four cases of GSER <Values>
761 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
762 * 2) '...'B or '...'H :
763 * BitStringVal, OctetStringVal
765 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
766 * 4) Between two white spaces
767 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
771 if ( cav->cav_ptr[0] == '"' ) {
772 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
773 /* In order to find escaped double quote */
774 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
775 else sequent_dquote = 0;
777 if ( cav->cav_ptr[count] == '\0' ||
778 (cav->cav_ptr+count) > cav->cav_end )
783 if ( ( cav->cav_ptr[count] == '"' &&
784 cav->cav_ptr[count-1] != '"') ||
785 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
792 if ( !succeed || cav->cav_ptr[count] != '"' ) {
793 return LDAP_FILTER_ERROR;
796 bv->bv_val = cav->cav_ptr + 1;
797 bv->bv_len = count - 1; /* exclude '"' */
799 } else if ( cav->cav_ptr[0] == '\'' ) {
800 for( count = 1 ; ; count++ ) {
801 if ( cav->cav_ptr[count] == '\0' ||
802 (cav->cav_ptr+count) > cav->cav_end )
806 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
807 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
815 !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
817 return LDAP_FILTER_ERROR;
820 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
821 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
823 } else if ( cav->cav_ptr[0] == '{' ) {
824 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
825 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
826 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
828 if ( cav->cav_ptr[count] == '\0' ||
829 (cav->cav_ptr+count) > cav->cav_end )
833 if ( unclosed_brace == 0 ) {
839 if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
841 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
842 bv->bv_len = count - 1;/* exclude "'B" */
846 /*Find following white space where the value is ended*/
847 for( count = 1 ; ; count++ ) {
848 if ( cav->cav_ptr[count] == '\0' ||
849 cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
850 cav->cav_ptr[count] == '{' ||
851 (cav->cav_ptr+count) > cav->cav_end )
856 bv->bv_val = cav->cav_ptr;
860 cav->cav_ptr += bv->bv_len;
865 get_matching_value( Operation *op, ComponentAssertion* ca,
866 ComponentAssertionValue* cav, struct berval* bv,
869 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
870 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
871 return LDAP_FILTER_ERROR;
875 /* embeded componentFilterMatch Description */
876 bv->bv_val = cav->cav_ptr;
877 bv->bv_len = cav_cur_len( cav );
883 /* Don't move the position pointer, just peek given string */
885 peek_cav_str( ComponentAssertionValue* cav, char* str )
888 if ( cav_cur_len( cav ) >= strlen( str ) &&
889 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
894 return LDAP_INVALID_SYNTAX;
898 strip_cav_str( ComponentAssertionValue* cav, char* str)
901 if ( cav_cur_len( cav ) >= strlen( str ) &&
902 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
904 cav->cav_ptr += strlen( str );
908 return LDAP_INVALID_SYNTAX;
912 * TAG : "item", "and", "or", "not"
915 strip_cav_tag( ComponentAssertionValue* cav )
919 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
920 strip_cav_str( cav , "item:" );
921 return LDAP_COMP_FILTER_ITEM;
923 } else if ( cav_cur_len( cav ) >= 7 &&
924 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
926 strip_cav_str( cav , "and:" );
927 return LDAP_COMP_FILTER_AND;
929 } else if ( cav_cur_len( cav ) >= 6 &&
930 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
932 strip_cav_str( cav , "or:" );
933 return LDAP_COMP_FILTER_OR;
935 } else if ( cav_cur_len( cav ) >= 7 &&
936 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
938 strip_cav_str( cav , "not:" );
939 return LDAP_COMP_FILTER_NOT;
946 * when encoding, "item" is denotation of ComponentAssertion
947 * ComponentAssertion :: SEQUENCE {
948 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
949 * useDefaultValues BOOLEAN DEFAULT TRUE,
950 * rule MATCHING-RULE.&id,
951 * value MATCHING-RULE.&AssertionType }
954 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
958 ComponentAssertion* _ca;
963 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
965 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
967 _ca = malloc( sizeof( ComponentAssertion ) );
969 if ( !_ca ) return LDAP_NO_MEMORY;
971 _ca->ca_comp_data.cd_tree = NULL;
972 _ca->ca_comp_data.cd_mem_op = NULL;
974 rc = peek_cav_str( cav, "component" );
975 if ( rc == LDAP_SUCCESS ) {
976 strip_cav_str( cav, "component" );
977 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
978 if ( rc != LDAP_SUCCESS ) {
980 op->o_tmpfree( _ca, op->o_tmpmemctx );
983 return LDAP_INVALID_SYNTAX;
985 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
988 _ca->ca_comp_ref = NULL;
991 rc = peek_cav_str( cav, "useDefaultValues");
992 if ( rc == LDAP_SUCCESS ) {
993 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
994 if ( rc != LDAP_SUCCESS ) {
996 op->o_tmpfree( _ca, op->o_tmpmemctx );
999 return LDAP_INVALID_SYNTAX;
1001 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1004 else _ca->ca_use_def = 1;
1006 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
1007 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
1009 op->o_tmpfree( _ca, op->o_tmpmemctx );
1012 return LDAP_INAPPROPRIATE_MATCHING;
1015 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1017 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1018 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1020 op->o_tmpfree( _ca, op->o_tmpmemctx );
1023 return LDAP_INVALID_SYNTAX;
1027 * Normalize the value of this component assertion when the matching
1028 * rule is one of existing matching rules
1030 mr = _ca->ca_ma_rule;
1031 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
1033 value.bv_val[value.bv_len] = '\0';
1034 rc = mr->smr_normalize (
1035 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
1037 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
1038 if ( rc != LDAP_SUCCESS )
1042 _ca->ca_ma_value = value;
1044 * Validate the value of this component assertion
1046 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1047 return LDAP_INVALID_SYNTAX;
1051 /* componentFilterMatch contains componentFilterMatch in it */
1052 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1054 bv.bv_val = cav->cav_ptr;
1055 bv.bv_len = cav_cur_len( cav );
1056 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1057 if ( rc != LDAP_SUCCESS ) {
1059 op->o_tmpfree( _ca, op->o_tmpmemctx );
1064 cav->cav_ptr = bv.bv_val;
1065 assert( cav->cav_end >= bv.bv_val );
1069 return LDAP_SUCCESS;
1073 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1074 ComponentFilter** filt, const char** text )
1077 * A component filter looks like this coming in:
1078 * Filter ::= CHOICE {
1079 * item [0] ComponentAssertion,
1080 * and [1] SEQUENCE OF ComponentFilter,
1081 * or [2] SEQUENCE OF ComponentFilter,
1082 * not [3] ComponentFilter,
1089 /* TAG : item, and, or, not in RFC 2254 */
1090 tag = strip_cav_tag( cav );
1092 if ( tag == LBER_ERROR ) {
1093 *text = "error decoding comp filter";
1094 return LDAP_PROTOCOL_ERROR;
1097 if ( tag != LDAP_COMP_FILTER_NOT )
1098 strip_cav_str( cav, "{");
1105 switch ( f.cf_choice ) {
1106 case LDAP_COMP_FILTER_AND:
1107 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1108 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1109 if ( err != LDAP_SUCCESS ) {
1112 if ( f.cf_and == NULL ) {
1113 f.cf_choice = SLAPD_FILTER_COMPUTED;
1114 f.cf_result = LDAP_COMPARE_TRUE;
1118 case LDAP_COMP_FILTER_OR:
1119 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1120 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1121 if ( err != LDAP_SUCCESS ) {
1124 if ( f.cf_or == NULL ) {
1125 f.cf_choice = SLAPD_FILTER_COMPUTED;
1126 f.cf_result = LDAP_COMPARE_FALSE;
1128 /* no assert - list could be empty */
1131 case LDAP_COMP_FILTER_NOT:
1132 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1133 err = parse_comp_filter( op, cav, &f.cf_not, text );
1134 if ( err != LDAP_SUCCESS ) {
1138 assert( f.cf_not != NULL );
1139 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1140 int fresult = f.cf_not->cf_result;
1141 f.cf_choice = SLAPD_FILTER_COMPUTED;
1142 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1145 switch ( fresult ) {
1146 case LDAP_COMPARE_TRUE:
1147 f.cf_result = LDAP_COMPARE_FALSE;
1149 case LDAP_COMPARE_FALSE:
1150 f.cf_result = LDAP_COMPARE_TRUE;
1153 /* (!Undefined) is Undefined */
1158 case LDAP_COMP_FILTER_ITEM:
1159 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1160 err = get_item( op, cav, &f.cf_ca, text );
1161 if ( err != LDAP_SUCCESS ) {
1165 assert( f.cf_ca != NULL );
1169 f.cf_choice = SLAPD_FILTER_COMPUTED;
1170 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1174 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1175 *text = "Component Filter Syntax Error";
1179 if ( tag != LDAP_COMP_FILTER_NOT )
1180 strip_cav_str( cav, "}");
1182 if ( err == LDAP_SUCCESS ) {
1184 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1186 *filt = malloc( sizeof(f) );
1195 test_comp_filter_and(
1197 ComponentSyntaxInfo *a,
1198 ComponentFilter *flist )
1201 int rtn = LDAP_COMPARE_TRUE;
1203 for ( f = flist ; f != NULL; f = f->cf_next ) {
1204 int rc = test_comp_filter( syn, a, f );
1205 if ( rc == LDAP_COMPARE_FALSE ) {
1210 if ( rc != LDAP_COMPARE_TRUE ) {
1219 test_comp_filter_or(
1221 ComponentSyntaxInfo *a,
1222 ComponentFilter *flist )
1225 int rtn = LDAP_COMPARE_TRUE;
1227 for ( f = flist ; f != NULL; f = f->cf_next ) {
1228 int rc = test_comp_filter( syn, a, f );
1229 if ( rc == LDAP_COMPARE_TRUE ) {
1234 if ( rc != LDAP_COMPARE_FALSE ) {
1243 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1244 struct berval* bv_assert )
1249 assert( mr != NULL );
1250 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1252 if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1254 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1255 mr, bv_attr, bv_assert );
1257 if ( rc != LDAP_SUCCESS ) return rc;
1259 return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1263 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1266 test_comp_filter_item(
1268 ComponentSyntaxInfo *csi_attr,
1269 ComponentAssertion *ca )
1272 void *attr_nm, *assert_nm;
1274 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1275 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1276 /* componentFilterMatch inside of componentFilterMatch */
1277 rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1281 /* Memory for storing will-be-extracted attribute values */
1282 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1283 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1285 /* Memory for storing component assertion values */
1286 if( !ca->ca_comp_data.cd_mem_op ) {
1287 assert_nm = nibble_mem_allocator ( 256, 64 );
1289 nibble_mem_free ( attr_nm );
1290 return LDAP_PROTOCOL_ERROR;
1292 ca->ca_comp_data.cd_mem_op = assert_nm;
1295 assert_nm = ca->ca_comp_data.cd_mem_op;
1298 /* component reference initialization */
1299 if ( ca->ca_comp_ref ) {
1300 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1302 rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1304 /* free memory used for storing extracted attribute value */
1305 nibble_mem_free ( attr_nm );
1312 ComponentSyntaxInfo *a,
1313 ComponentFilter *f )
1317 if ( !f ) return LDAP_PROTOCOL_ERROR;
1319 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1320 switch ( f->cf_choice ) {
1321 case SLAPD_FILTER_COMPUTED:
1324 case LDAP_COMP_FILTER_AND:
1325 rc = test_comp_filter_and( syn, a, f->cf_and );
1327 case LDAP_COMP_FILTER_OR:
1328 rc = test_comp_filter_or( syn, a, f->cf_or );
1330 case LDAP_COMP_FILTER_NOT:
1331 rc = test_comp_filter( syn, a, f->cf_not );
1334 case LDAP_COMPARE_TRUE:
1335 rc = LDAP_COMPARE_FALSE;
1337 case LDAP_COMPARE_FALSE:
1338 rc = LDAP_COMPARE_TRUE;
1342 case LDAP_COMP_FILTER_ITEM:
1343 rc = test_comp_filter_item( syn, a, f->cf_ca );
1346 rc = LDAP_PROTOCOL_ERROR;
1353 free_comp_filter_list( ComponentFilter* f )
1355 ComponentFilter* tmp;
1356 for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1357 free_comp_filter( tmp );
1362 free_comp_filter( ComponentFilter* f )
1365 Debug( LDAP_DEBUG_FILTER,
1366 "free_comp_filter: Invalid filter so failed to release memory\n",
1370 switch ( f->cf_choice ) {
1371 case LDAP_COMP_FILTER_AND:
1372 case LDAP_COMP_FILTER_OR:
1373 free_comp_filter_list( f->cf_any );
1375 case LDAP_COMP_FILTER_NOT:
1376 free_comp_filter( f->cf_any );
1378 case LDAP_COMP_FILTER_ITEM:
1379 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1380 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1389 component_free( ComponentFilter *f ) {
1390 free_comp_filter( f );
1394 free_ComponentData( Attribute *a ) {
1395 if ( a->a_comp_data->cd_mem_op )
1396 component_destructor( a->a_comp_data->cd_mem_op );
1397 free ( a->a_comp_data );
1398 a->a_comp_data = NULL;