1 /* filter.c - routines for parsing and dealing with filters */
4 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/socket.h>
13 #include <ac/string.h>
17 static int get_filter_list(
24 static int get_substring_filter(
31 static int filter_escape_value(
48 struct berval escaped;
51 LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY, "get_filter: conn %d\n",
54 Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
57 * A filter looks like this coming in:
59 * and [0] SET OF Filter,
60 * or [1] SET OF Filter,
62 * equalityMatch [3] AttributeValueAssertion,
63 * substrings [4] SubstringFilter,
64 * greaterOrEqual [5] AttributeValueAssertion,
65 * lessOrEqual [6] AttributeValueAssertion,
66 * present [7] AttributeType,,
67 * approxMatch [8] AttributeValueAssertion
68 * extensibleMatch [9] MatchingRuleAssertion
71 * SubstringFilter ::= SEQUENCE {
73 * SEQUENCE OF CHOICE {
74 * initial [0] IA5String,
80 * MatchingRuleAssertion ::= SEQUENCE {
81 * matchingRule [1] MatchingRuleId OPTIONAL,
82 * type [2] AttributeDescription OPTIONAL,
83 * matchValue [3] AssertionValue,
84 * dnAttributes [4] BOOLEAN DEFAULT FALSE
89 tag = ber_peek_tag( ber, &len );
91 if( tag == LBER_ERROR ) {
92 *text = "error decoding filter";
93 return SLAPD_DISCONNECT;
96 f = (Filter *) ch_malloc( sizeof(Filter) );
103 switch ( f->f_choice ) {
104 case LDAP_FILTER_EQUALITY:
106 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL2,
107 "get_filter: conn %d EQUALITY\n", conn->c_connid ));
109 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
111 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY, text );
112 if ( err != LDAP_SUCCESS ) {
116 assert( f->f_ava != NULL );
118 filter_escape_value( f->f_av_value, &escaped );
120 *fstr = ch_malloc( sizeof("(=)")
121 + f->f_av_desc->ad_cname.bv_len
124 sprintf( *fstr, "(%s=%s)",
125 f->f_av_desc->ad_cname.bv_val,
128 ber_memfree( escaped.bv_val );
131 case LDAP_FILTER_SUBSTRINGS:
133 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
134 "get_filter: conn %d SUBSTRINGS\n", conn->c_connid ));
136 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
138 err = get_substring_filter( conn, ber, f, fstr, text );
143 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
144 "get_filter: conn %d GE\n", conn->c_connid ));
146 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
148 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
149 if ( err != LDAP_SUCCESS ) {
153 filter_escape_value( f->f_av_value, &escaped );
155 *fstr = ch_malloc( sizeof("(>=)")
156 + f->f_av_desc->ad_cname.bv_len
159 sprintf( *fstr, "(%s>=%s)",
160 f->f_av_desc->ad_cname.bv_val,
163 ber_memfree( escaped.bv_val );
168 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
169 "get_filter: conn %d LE\n", conn->c_connid ));
171 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
173 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
174 if ( err != LDAP_SUCCESS ) {
179 filter_escape_value( f->f_av_value, &escaped );
181 *fstr = ch_malloc( sizeof("(<=)")
182 + f->f_av_desc->ad_cname.bv_len
185 sprintf( *fstr, "(%s<=%s)",
186 f->f_av_desc->ad_cname.bv_val,
189 ber_memfree( escaped.bv_val );
192 case LDAP_FILTER_PRESENT: {
196 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
197 "get_filter: conn %d PRESENT\n", conn->c_connid ));
199 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
201 if ( ber_scanf( ber, "o", &type ) == LBER_ERROR ) {
202 err = SLAPD_DISCONNECT;
203 *text = "error decoding filter";
208 err = slap_bv2ad( &type, &f->f_desc, text );
210 if( err != LDAP_SUCCESS ) {
211 /* unrecognized attribute description or other error */
212 f->f_choice = SLAPD_FILTER_COMPUTED;
213 f->f_result = LDAP_COMPARE_FALSE;
214 *fstr = ch_strdup( "(unrecogized=*)" );
215 ch_free( type.bv_val );
220 ch_free( type.bv_val );
222 *fstr = ch_malloc( sizeof("(=*)")
223 + f->f_desc->ad_cname.bv_len );
224 sprintf( *fstr, "(%s=*)",
225 f->f_desc->ad_cname.bv_val );
229 case LDAP_FILTER_APPROX:
231 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
232 "get_filter: conn %d APPROX\n", conn->c_connid ));
234 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
236 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY_APPROX, text );
237 if ( err != LDAP_SUCCESS ) {
241 filter_escape_value( f->f_av_value, &escaped );
243 *fstr = ch_malloc( sizeof("(~=)")
244 + f->f_av_desc->ad_cname.bv_len
247 sprintf( *fstr, "(%s~=%s)",
248 f->f_av_desc->ad_cname.bv_val,
251 ber_memfree( escaped.bv_val );
254 case LDAP_FILTER_AND:
256 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
257 "get_filter: conn %d AND\n", conn->c_connid ));
259 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
261 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
262 if ( err != LDAP_SUCCESS ) {
265 *fstr = ch_malloc( sizeof("(&)")
266 + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
267 sprintf( *fstr, "(&%s)",
268 ftmp == NULL ? "" : ftmp );
273 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
274 "get_filter: conn %d OR\n", conn->c_connid ));
276 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
278 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
279 if ( err != LDAP_SUCCESS ) {
282 *fstr = ch_malloc( sizeof("(!)")
283 + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
284 sprintf( *fstr, "(|%s)",
285 ftmp == NULL ? "" : ftmp );
288 case LDAP_FILTER_NOT:
290 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
291 "get_filter: conn %d NOT\n", conn->c_connid ));
293 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
295 (void) ber_skip_tag( ber, &len );
296 err = get_filter( conn, ber, &f->f_not, &ftmp, text );
297 if ( err != LDAP_SUCCESS ) {
300 *fstr = ch_malloc( sizeof("(!)")
301 + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
302 sprintf( *fstr, "(!%s)",
303 ftmp == NULL ? "" : ftmp );
306 case LDAP_FILTER_EXT:
308 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
309 "get_filter: conn %d EXTENSIBLE\n", conn->c_connid ));
311 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
314 err = get_mra( ber, &f->f_mra, text );
315 if ( err != LDAP_SUCCESS ) {
319 assert( f->f_mra != NULL );
321 filter_escape_value( f->f_mr_value, &escaped );
323 *fstr = ch_malloc( sizeof("(:dn::=)")
324 + (f->f_mr_desc ? f->f_mr_desc->ad_cname.bv_len : 0)
325 + (f->f_mr_rule_text ? strlen(f->f_mr_rule_text) : 0)
328 sprintf( *fstr, "(%s%s%s%s:=%s)",
329 (f->f_mr_desc ? f->f_mr_desc->ad_cname.bv_val : ""),
330 (f->f_mr_dnattrs ? ":dn" : ""),
331 (f->f_mr_rule_text ? ":" : ""),
332 (f->f_mr_rule_text ? f->f_mr_rule_text : ""),
335 ber_memfree( escaped.bv_val );
339 (void) ber_scanf( ber, "x" ); /* skip the element */
341 LDAP_LOG(( "filter", LDAP_LEVEL_ERR,
342 "get_filter: conn %d unknown filter type=%lu\n",
343 conn->c_connid, f->f_choice ));
345 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
348 f->f_choice = SLAPD_FILTER_COMPUTED;
349 f->f_result = SLAPD_COMPARE_UNDEFINED;
350 *fstr = ch_strdup( "(undefined)" );
356 if ( err != LDAP_SUCCESS ) {
357 if ( *fstr != NULL ) {
361 if( err != SLAPD_DISCONNECT ) {
363 f->f_choice = SLAPD_FILTER_COMPUTED;
364 f->f_result = SLAPD_COMPARE_UNDEFINED;
365 *fstr = ch_strdup( "(badfilter)" );
377 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL2,
378 "get_filter: conn %d exit\n", conn->c_connid ));
380 Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
386 get_filter_list( Connection *conn, BerElement *ber,
387 Filter **f, char **fstr,
397 LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
398 "get_filter_list: conn %d start\n", conn->c_connid ));
400 Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
404 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
405 tag = ber_next_element( ber, &len, last ) )
407 err = get_filter( conn, ber, new, &ftmp, text );
408 if ( err != LDAP_SUCCESS )
411 if ( *fstr == NULL ) {
414 *fstr = ch_realloc( *fstr, strlen( *fstr ) +
415 strlen( ftmp ) + 1 );
416 strcat( *fstr, ftmp );
419 new = &(*new)->f_next;
424 LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
425 "get_filter_list: conn %d exit\n", conn->c_connid ));
427 Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
429 return( LDAP_SUCCESS );
433 get_substring_filter(
444 struct berval *value;
445 struct berval escaped;
448 struct berval *nvalue;
449 *text = "error decoding filter";
452 LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
453 "get_substring_filter: conn %d begin\n", conn->c_connid ));
455 Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
457 if ( ber_scanf( ber, "{o" /*}*/, &type ) == LBER_ERROR ) {
458 return SLAPD_DISCONNECT;
461 f->f_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
462 f->f_sub_desc = NULL;
463 rc = slap_bv2ad( &type, &f->f_sub_desc, text );
465 ch_free( type.bv_val );
467 if( rc != LDAP_SUCCESS ) {
470 f->f_choice = SLAPD_FILTER_COMPUTED;
471 f->f_result = SLAPD_COMPARE_UNDEFINED;
472 *fstr = ch_strdup( "(undefined)" );
476 f->f_sub_initial = NULL;
478 f->f_sub_final = NULL;
481 *fstr = ch_malloc( sizeof("(=" /*)*/) +
482 f->f_sub_desc->ad_cname.bv_len );
483 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_desc->ad_cname.bv_val );
486 for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
487 tag = ber_next_element( ber, &len, last ) )
491 rc = ber_scanf( ber, "O", &value );
492 if ( rc == LBER_ERROR ) {
493 rc = SLAPD_DISCONNECT;
497 if ( value == NULL || value->bv_len == 0 ) {
499 rc = LDAP_INVALID_SYNTAX;
504 case LDAP_SUBSTRING_INITIAL:
505 usage = SLAP_MR_SUBSTR_INITIAL;
508 case LDAP_SUBSTRING_ANY:
509 usage = SLAP_MR_SUBSTR_ANY;
512 case LDAP_SUBSTRING_FINAL:
513 usage = SLAP_MR_SUBSTR_FINAL;
517 rc = LDAP_PROTOCOL_ERROR;
520 LDAP_LOG(( "filter", LDAP_LEVEL_ERR,
521 "get_filter_substring: conn %d unknown substring choice=%ld\n",
522 conn->c_connid, (long)tag ));
524 Debug( LDAP_DEBUG_FILTER,
525 " unknown substring choice=%ld\n",
532 rc = value_normalize( f->f_sub_desc, usage, value, &nvalue, text );
535 if( rc != LDAP_SUCCESS ) {
541 rc = LDAP_PROTOCOL_ERROR;
544 case LDAP_SUBSTRING_INITIAL:
546 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
547 "get_substring_filter: conn %d INITIAL\n",
550 Debug( LDAP_DEBUG_FILTER, " INITIAL\n", 0, 0, 0 );
553 if ( f->f_sub_initial != NULL
554 || f->f_sub_any != NULL
555 || f->f_sub_final != NULL )
561 f->f_sub_initial = value;
564 filter_escape_value( value, &escaped );
565 *fstr = ch_realloc( *fstr,
566 strlen( *fstr ) + escaped.bv_len + 1 );
567 strcat( *fstr, escaped.bv_val );
568 ber_memfree( escaped.bv_val );
572 case LDAP_SUBSTRING_ANY:
574 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
575 "get_substring_filter: conn %d ANY\n",
578 Debug( LDAP_DEBUG_FILTER, " ANY\n", 0, 0, 0 );
581 if ( f->f_sub_final != NULL ) {
586 if( ber_bvecadd( &f->f_sub_any, value ) < 0 ) {
592 filter_escape_value( value, &escaped );
593 *fstr = ch_realloc( *fstr,
594 strlen( *fstr ) + escaped.bv_len + 2 );
595 strcat( *fstr, "*" );
596 strcat( *fstr, escaped.bv_val );
597 ber_memfree( escaped.bv_val );
601 case LDAP_SUBSTRING_FINAL:
603 LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
604 "get_substring_filter: conn %d FINAL\n",
607 Debug( LDAP_DEBUG_FILTER, " FINAL\n", 0, 0, 0 );
610 if ( f->f_sub_final != NULL ) {
615 f->f_sub_final = value;
618 filter_escape_value( value, &escaped );
619 *fstr = ch_realloc( *fstr,
620 strlen( *fstr ) + escaped.bv_len + 2 );
621 strcat( *fstr, "*" );
622 strcat( *fstr, escaped.bv_val );
623 ber_memfree( escaped.bv_val );
629 LDAP_LOG(( "filter", LDAP_LEVEL_INFO,
630 "get_substring_filter: conn %d unknown substring type %ld\n",
631 conn->c_connid, (long)tag ));
633 Debug( LDAP_DEBUG_FILTER,
634 " unknown substring type=%ld\n",
642 LDAP_LOG(( "filter", LDAP_LEVEL_INFO,
643 "get_substring_filter: conn %d error %ld\n",
644 conn->c_connid, (long)rc ));
646 Debug( LDAP_DEBUG_FILTER, " error=%ld\n",
654 ber_bvfree( f->f_sub_initial );
655 ber_bvecfree( f->f_sub_any );
656 ber_bvfree( f->f_sub_final );
663 *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
664 if ( f->f_sub_final == NULL ) {
665 strcat( *fstr, "*" );
667 strcat( *fstr, /*(*/ ")" );
671 LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
672 "get_substring_filter: conn %d exit\n", conn->c_connid ));
674 Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
676 return( LDAP_SUCCESS );
680 filter_free( Filter *f )
688 switch ( f->f_choice ) {
689 case LDAP_FILTER_PRESENT:
692 case LDAP_FILTER_EQUALITY:
695 case LDAP_FILTER_APPROX:
696 ava_free( f->f_ava, 1 );
699 case LDAP_FILTER_SUBSTRINGS:
700 if ( f->f_sub_initial != NULL ) {
701 ber_bvfree( f->f_sub_initial );
703 ber_bvecfree( f->f_sub_any );
704 if ( f->f_sub_final != NULL ) {
705 ber_bvfree( f->f_sub_final );
710 case LDAP_FILTER_AND:
712 case LDAP_FILTER_NOT:
713 for ( p = f->f_list; p != NULL; p = next ) {
719 case SLAPD_FILTER_COMPUTED:
724 LDAP_LOG(( "filter", LDAP_LEVEL_ERR,
725 "filter_free: unknown filter type %lu\n", f->f_choice ));
727 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
738 filter_print( Filter *f )
742 struct berval escaped;
745 fprintf( stderr, "No filter!" );
748 switch ( f->f_choice ) {
749 case LDAP_FILTER_EQUALITY:
750 filter_escape_value( f->f_av_value, &escaped );
751 fprintf( stderr, "(%s=%s)",
752 f->f_av_desc->ad_cname.bv_val,
754 ber_memfree( escaped.bv_val );
758 filter_escape_value( f->f_av_value, &escaped );
759 fprintf( stderr, "(%s>=%s)",
760 f->f_av_desc->ad_cname.bv_val,
762 ber_memfree( escaped.bv_val );
766 filter_escape_value( f->f_av_value, &escaped );
767 fprintf( stderr, "(%s<=%s)",
768 f->f_ava->aa_desc->ad_cname.bv_val,
770 ber_memfree( escaped.bv_val );
773 case LDAP_FILTER_APPROX:
774 filter_escape_value( f->f_av_value, &escaped );
775 fprintf( stderr, "(%s~=%s)",
776 f->f_ava->aa_desc->ad_cname.bv_val,
778 ber_memfree( escaped.bv_val );
781 case LDAP_FILTER_SUBSTRINGS:
782 fprintf( stderr, "(%s=" /*)*/,
783 f->f_sub_desc->ad_cname.bv_val );
784 if ( f->f_sub_initial != NULL ) {
785 filter_escape_value( f->f_sub_initial, &escaped );
786 fprintf( stderr, "%s",
788 ber_memfree( escaped.bv_val );
790 if ( f->f_sub_any != NULL ) {
791 for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
792 filter_escape_value( f->f_sub_any[i], &escaped );
793 fprintf( stderr, "*%s",
795 ber_memfree( escaped.bv_val );
798 if ( f->f_sub_final != NULL ) {
799 filter_escape_value( f->f_sub_final, &escaped );
801 "*%s", escaped.bv_val );
802 ber_memfree( escaped.bv_val );
804 fprintf( stderr, /*(*/ ")" );
807 case LDAP_FILTER_PRESENT:
808 fprintf( stderr, "(%s=*)",
809 f->f_desc->ad_cname.bv_val );
812 case LDAP_FILTER_AND:
814 case LDAP_FILTER_NOT:
815 fprintf( stderr, "(%c" /*)*/,
816 f->f_choice == LDAP_FILTER_AND ? '&' :
817 f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
818 for ( p = f->f_list; p != NULL; p = p->f_next ) {
821 fprintf( stderr, /*(*/ ")" );
824 case SLAPD_FILTER_COMPUTED:
825 fprintf( stderr, "(?=%s)",
826 f->f_result == LDAP_COMPARE_FALSE ? "false" :
827 f->f_result == LDAP_COMPARE_TRUE ? "true" :
828 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
833 fprintf( stderr, "(unknown-filter=%lu)", f->f_choice );
838 #endif /* ldap_debug */
840 int filter_escape_value(
848 out->bv_val = (char *) ch_malloc( ( in->bv_len * 3 ) + 1 );
851 for( i=0; i < in->bv_len ; i++ ) {
852 if( FILTER_ESCAPE(in->bv_val[i]) ) {
853 out->bv_val[out->bv_len++] = SLAP_ESCAPE_CHAR;
854 out->bv_val[out->bv_len++] = SLAP_ESCAPE_HI( in->bv_val[i] );
855 out->bv_val[out->bv_len++] = SLAP_ESCAPE_LO( in->bv_val[i] );
857 out->bv_val[out->bv_len++] = in->bv_val[i];
861 out->bv_val[out->bv_len] = '\0';