Back to index

openldap  2.4.31
filter.c
Go to the documentation of this file.
00001 /* filter.c - routines for parsing and dealing with filters */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 
00027 #include "portable.h"
00028 
00029 #include <stdio.h>
00030 
00031 #include <ac/socket.h>
00032 #include <ac/string.h>
00033 
00034 #include "slap.h"
00035 #include "lutil.h"
00036 
00037 const Filter *slap_filter_objectClass_pres;
00038 const struct berval *slap_filterstr_objectClass_pres;
00039 
00040 static int    get_filter_list(
00041        Operation *op,
00042        BerElement *ber,
00043        Filter **f,
00044        const char **text );
00045 
00046 static int    get_ssa(
00047        Operation *op,
00048        BerElement *ber,
00049        Filter *f,
00050        const char **text );
00051 
00052 static void simple_vrFilter2bv(
00053        Operation *op,
00054        ValuesReturnFilter *f,
00055        struct berval *fstr );
00056 
00057 static int    get_simple_vrFilter(
00058        Operation *op,
00059        BerElement *ber,
00060        ValuesReturnFilter **f,
00061        const char **text );
00062 
00063 int
00064 filter_init( void )
00065 {
00066        static Filter filter_objectClass_pres = { LDAP_FILTER_PRESENT };
00067        static struct berval filterstr_objectClass_pres = BER_BVC("(objectClass=*)");
00068 
00069        filter_objectClass_pres.f_desc = slap_schema.si_ad_objectClass;
00070 
00071        slap_filter_objectClass_pres = &filter_objectClass_pres;
00072        slap_filterstr_objectClass_pres = &filterstr_objectClass_pres;
00073 
00074        return 0;
00075 }
00076 
00077 void
00078 filter_destroy( void )
00079 {
00080        return;
00081 }
00082 
00083 int
00084 get_filter(
00085        Operation *op,
00086        BerElement *ber,
00087        Filter **filt,
00088        const char **text )
00089 {
00090        ber_tag_t     tag;
00091        ber_len_t     len;
00092        int           err;
00093        Filter        f;
00094 
00095        Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
00096        /*
00097         * A filter looks like this coming in:
00098         *     Filter ::= CHOICE {
00099         *            and           [0]    SET OF Filter,
00100         *            or            [1]    SET OF Filter,
00101         *            not           [2]    Filter,
00102         *            equalityMatch [3]    AttributeValueAssertion,
00103         *            substrings    [4]    SubstringFilter,
00104         *            greaterOrEqual       [5]    AttributeValueAssertion,
00105         *            lessOrEqual   [6]    AttributeValueAssertion,
00106         *            present              [7]    AttributeType,
00107         *            approxMatch   [8]    AttributeValueAssertion,
00108         *            extensibleMatch [9]  MatchingRuleAssertion
00109         *     }
00110         *
00111         *     SubstringFilter ::= SEQUENCE {
00112         *            type             AttributeType,
00113         *            SEQUENCE OF CHOICE {
00114         *                   initial               [0] IA5String,
00115         *                   any            [1] IA5String,
00116         *                   final          [2] IA5String
00117         *            }
00118         *     }
00119         *
00120         *     MatchingRuleAssertion ::= SEQUENCE {
00121         *            matchingRule  [1] MatchingRuleId OPTIONAL,
00122         *            type          [2] AttributeDescription OPTIONAL,
00123         *            matchValue    [3] AssertionValue,
00124         *            dnAttributes  [4] BOOLEAN DEFAULT FALSE
00125         *     }
00126         *
00127         */
00128 
00129        tag = ber_peek_tag( ber, &len );
00130 
00131        if( tag == LBER_ERROR ) {
00132               *text = "error decoding filter";
00133               return SLAPD_DISCONNECT;
00134        }
00135 
00136        err = LDAP_SUCCESS;
00137 
00138        f.f_next = NULL;
00139        f.f_choice = tag; 
00140 
00141        switch ( f.f_choice ) {
00142        case LDAP_FILTER_EQUALITY:
00143               Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
00144               err = get_ava( op, ber, &f, SLAP_MR_EQUALITY, text );
00145               if ( err != LDAP_SUCCESS ) {
00146                      break;
00147               }
00148 
00149               assert( f.f_ava != NULL );
00150               break;
00151 
00152        case LDAP_FILTER_SUBSTRINGS:
00153               Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
00154               err = get_ssa( op, ber, &f, text );
00155               if( err != LDAP_SUCCESS ) {
00156                      break;
00157               }
00158               assert( f.f_sub != NULL );
00159               break;
00160 
00161        case LDAP_FILTER_GE:
00162               Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
00163               err = get_ava( op, ber, &f, SLAP_MR_ORDERING, text );
00164               if ( err != LDAP_SUCCESS ) {
00165                      break;
00166               }
00167               assert( f.f_ava != NULL );
00168               break;
00169 
00170        case LDAP_FILTER_LE:
00171               Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
00172               err = get_ava( op, ber, &f, SLAP_MR_ORDERING, text );
00173               if ( err != LDAP_SUCCESS ) {
00174                      break;
00175               }
00176               assert( f.f_ava != NULL );
00177               break;
00178 
00179        case LDAP_FILTER_PRESENT: {
00180               struct berval type;
00181 
00182               Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
00183               if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
00184                      err = SLAPD_DISCONNECT;
00185                      *text = "error decoding filter";
00186                      break;
00187               }
00188 
00189               f.f_desc = NULL;
00190               err = slap_bv2ad( &type, &f.f_desc, text );
00191 
00192               if( err != LDAP_SUCCESS ) {
00193                      f.f_choice |= SLAPD_FILTER_UNDEFINED;
00194                      err = slap_bv2undef_ad( &type, &f.f_desc, text,
00195                             SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
00196 
00197                      if ( err != LDAP_SUCCESS ) {
00198                             /* unrecognized attribute description or other error */
00199                             Debug( LDAP_DEBUG_ANY, 
00200                                    "get_filter: conn %lu unknown attribute "
00201                                    "type=%s (%d)\n",
00202                                    op->o_connid, type.bv_val, err );
00203 
00204                             err = LDAP_SUCCESS;
00205                             f.f_desc = slap_bv2tmp_ad( &type, op->o_tmpmemctx );
00206                      }
00207                      *text = NULL;
00208               }
00209 
00210               assert( f.f_desc != NULL );
00211               } break;
00212 
00213        case LDAP_FILTER_APPROX:
00214               Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
00215               err = get_ava( op, ber, &f, SLAP_MR_EQUALITY_APPROX, text );
00216               if ( err != LDAP_SUCCESS ) {
00217                      break;
00218               }
00219               assert( f.f_ava != NULL );
00220               break;
00221 
00222        case LDAP_FILTER_AND:
00223               Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
00224               err = get_filter_list( op, ber, &f.f_and, text );
00225               if ( err != LDAP_SUCCESS ) {
00226                      break;
00227               }
00228               if ( f.f_and == NULL ) {
00229                      f.f_choice = SLAPD_FILTER_COMPUTED;
00230                      f.f_result = LDAP_COMPARE_TRUE;
00231               }
00232               /* no assert - list could be empty */
00233               break;
00234 
00235        case LDAP_FILTER_OR:
00236               Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
00237               err = get_filter_list( op, ber, &f.f_or, text );
00238               if ( err != LDAP_SUCCESS ) {
00239                      break;
00240               }
00241               if ( f.f_or == NULL ) {
00242                      f.f_choice = SLAPD_FILTER_COMPUTED;
00243                      f.f_result = LDAP_COMPARE_FALSE;
00244               }
00245               /* no assert - list could be empty */
00246               break;
00247 
00248        case LDAP_FILTER_NOT:
00249               Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
00250               (void) ber_skip_tag( ber, &len );
00251               err = get_filter( op, ber, &f.f_not, text );
00252               if ( err != LDAP_SUCCESS ) {
00253                      break;
00254               }
00255 
00256               assert( f.f_not != NULL );
00257               if ( f.f_not->f_choice == SLAPD_FILTER_COMPUTED ) {
00258                      int fresult = f.f_not->f_result;
00259                      f.f_choice = SLAPD_FILTER_COMPUTED;
00260                      op->o_tmpfree( f.f_not, op->o_tmpmemctx );
00261                      f.f_not = NULL;
00262 
00263                      switch( fresult ) {
00264                      case LDAP_COMPARE_TRUE:
00265                             f.f_result = LDAP_COMPARE_FALSE;
00266                             break;
00267                      case LDAP_COMPARE_FALSE:
00268                             f.f_result = LDAP_COMPARE_TRUE;
00269                             break;
00270                      default: ;
00271                             /* (!Undefined) is Undefined */
00272                      }
00273               }
00274               break;
00275 
00276        case LDAP_FILTER_EXT:
00277               Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
00278 
00279               err = get_mra( op, ber, &f, text );
00280               if ( err != LDAP_SUCCESS ) {
00281                      break;
00282               }
00283 
00284               assert( f.f_mra != NULL );
00285               break;
00286 
00287        default:
00288               (void) ber_scanf( ber, "x" ); /* skip the element */
00289               Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
00290                      f.f_choice, 0, 0 );
00291               f.f_choice = SLAPD_FILTER_COMPUTED;
00292               f.f_result = SLAPD_COMPARE_UNDEFINED;
00293               break;
00294        }
00295 
00296        if( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
00297               /* ignore error */
00298               *text = NULL;
00299               f.f_choice = SLAPD_FILTER_COMPUTED;
00300               f.f_result = SLAPD_COMPARE_UNDEFINED;
00301               err = LDAP_SUCCESS;
00302        }
00303 
00304        if ( err == LDAP_SUCCESS ) {
00305               *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
00306               **filt = f;
00307        }
00308 
00309        Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
00310 
00311        return( err );
00312 }
00313 
00314 static int
00315 get_filter_list( Operation *op, BerElement *ber,
00316        Filter **f,
00317        const char **text )
00318 {
00319        Filter        **new;
00320        int           err;
00321        ber_tag_t     tag;
00322        ber_len_t     len;
00323        char          *last;
00324 
00325        Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
00326        new = f;
00327        for ( tag = ber_first_element( ber, &len, &last );
00328               tag != LBER_DEFAULT;
00329               tag = ber_next_element( ber, &len, last ) )
00330        {
00331               err = get_filter( op, ber, new, text );
00332               if ( err != LDAP_SUCCESS )
00333                      return( err );
00334               new = &(*new)->f_next;
00335        }
00336        *new = NULL;
00337 
00338        Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
00339        return( LDAP_SUCCESS );
00340 }
00341 
00342 static int
00343 get_ssa(
00344        Operation *op,
00345        BerElement    *ber,
00346        Filter               *f,
00347        const char    **text )
00348 {
00349        ber_tag_t     tag;
00350        ber_len_t     len;
00351        int    rc;
00352        struct berval desc, value, nvalue;
00353        char          *last;
00354        SubstringsAssertion ssa;
00355 
00356        *text = "error decoding filter";
00357 
00358        Debug( LDAP_DEBUG_FILTER, "begin get_ssa\n", 0, 0, 0 );
00359        if ( ber_scanf( ber, "{m" /*}*/, &desc ) == LBER_ERROR ) {
00360               return SLAPD_DISCONNECT;
00361        }
00362 
00363        *text = NULL;
00364 
00365        ssa.sa_desc = NULL;
00366        ssa.sa_initial.bv_val = NULL;
00367        ssa.sa_any = NULL;
00368        ssa.sa_final.bv_val = NULL;
00369 
00370        rc = slap_bv2ad( &desc, &ssa.sa_desc, text );
00371 
00372        if( rc != LDAP_SUCCESS ) {
00373               f->f_choice |= SLAPD_FILTER_UNDEFINED;
00374               rc = slap_bv2undef_ad( &desc, &ssa.sa_desc, text,
00375                      SLAP_AD_PROXIED|SLAP_AD_NOINSERT );
00376 
00377               if( rc != LDAP_SUCCESS ) {
00378                      Debug( LDAP_DEBUG_ANY, 
00379                             "get_ssa: conn %lu unknown attribute type=%s (%ld)\n",
00380                             op->o_connid, desc.bv_val, (long) rc );
00381        
00382                      ssa.sa_desc = slap_bv2tmp_ad( &desc, op->o_tmpmemctx );
00383               }
00384        }
00385 
00386        rc = LDAP_PROTOCOL_ERROR;
00387 
00388        /* If there is no substring matching rule, there's nothing
00389         * we can do with this filter. But we continue to parse it
00390         * for logging purposes.
00391         */
00392        if ( ssa.sa_desc->ad_type->sat_substr == NULL ) {
00393               f->f_choice |= SLAPD_FILTER_UNDEFINED;
00394               Debug( LDAP_DEBUG_FILTER,
00395               "get_ssa: no substring matching rule for attributeType %s\n",
00396                      desc.bv_val, 0, 0 );
00397        }
00398 
00399        for ( tag = ber_first_element( ber, &len, &last );
00400               tag != LBER_DEFAULT;
00401               tag = ber_next_element( ber, &len, last ) )
00402        {
00403               unsigned usage;
00404 
00405               if ( ber_scanf( ber, "m", &value ) == LBER_ERROR ) {
00406                      rc = SLAPD_DISCONNECT;
00407                      goto return_error;
00408               }
00409 
00410               if ( value.bv_val == NULL || value.bv_len == 0 ) {
00411                      rc = LDAP_INVALID_SYNTAX;
00412                      goto return_error;
00413               } 
00414 
00415               switch ( tag ) {
00416               case LDAP_SUBSTRING_INITIAL:
00417                      if ( ssa.sa_initial.bv_val != NULL
00418                             || ssa.sa_any != NULL 
00419                             || ssa.sa_final.bv_val != NULL )
00420                      {
00421                             rc = LDAP_PROTOCOL_ERROR;
00422                             goto return_error;
00423                      }
00424                      usage = SLAP_MR_SUBSTR_INITIAL;
00425                      break;
00426 
00427               case LDAP_SUBSTRING_ANY:
00428                      if ( ssa.sa_final.bv_val != NULL ) {
00429                             rc = LDAP_PROTOCOL_ERROR;
00430                             goto return_error;
00431                      }
00432                      usage = SLAP_MR_SUBSTR_ANY;
00433                      break;
00434 
00435               case LDAP_SUBSTRING_FINAL:
00436                      if ( ssa.sa_final.bv_val != NULL ) {
00437                             rc = LDAP_PROTOCOL_ERROR;
00438                             goto return_error;
00439                      }
00440 
00441                      usage = SLAP_MR_SUBSTR_FINAL;
00442                      break;
00443 
00444               default:
00445                      Debug( LDAP_DEBUG_FILTER,
00446                             "  unknown substring choice=%ld\n",
00447                             (long) tag, 0, 0 );
00448 
00449                      rc = LDAP_PROTOCOL_ERROR;
00450                      goto return_error;
00451               }
00452 
00453               /* validate/normalize using equality matching rule validator! */
00454               rc = asserted_value_validate_normalize(
00455                      ssa.sa_desc, ssa.sa_desc->ad_type->sat_equality,
00456                      usage, &value, &nvalue, text, op->o_tmpmemctx );
00457               if( rc != LDAP_SUCCESS ) {
00458                      f->f_choice |= SLAPD_FILTER_UNDEFINED;
00459                      Debug( LDAP_DEBUG_FILTER,
00460                      "get_ssa: illegal value for attributeType %s (%d) %s\n",
00461                             desc.bv_val, rc, *text );
00462                      ber_dupbv_x( &nvalue, &value, op->o_tmpmemctx );
00463               }
00464 
00465               switch ( tag ) {
00466               case LDAP_SUBSTRING_INITIAL:
00467                      Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
00468                      ssa.sa_initial = nvalue;
00469                      break;
00470 
00471               case LDAP_SUBSTRING_ANY:
00472                      Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
00473                      ber_bvarray_add_x( &ssa.sa_any, &nvalue, op->o_tmpmemctx );
00474                      break;
00475 
00476               case LDAP_SUBSTRING_FINAL:
00477                      Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
00478                      ssa.sa_final = nvalue;
00479                      break;
00480 
00481               default:
00482                      assert( 0 );
00483                      slap_sl_free( nvalue.bv_val, op->o_tmpmemctx );
00484                      rc = LDAP_PROTOCOL_ERROR;
00485 
00486 return_error:
00487                      Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
00488                             (long) rc, 0, 0 );
00489                      slap_sl_free( ssa.sa_initial.bv_val, op->o_tmpmemctx );
00490                      ber_bvarray_free_x( ssa.sa_any, op->o_tmpmemctx );
00491                      if ( ssa.sa_desc->ad_flags & SLAP_DESC_TEMPORARY )
00492                             op->o_tmpfree( ssa.sa_desc, op->o_tmpmemctx );
00493                      slap_sl_free( ssa.sa_final.bv_val, op->o_tmpmemctx );
00494                      return rc;
00495               }
00496 
00497               *text = NULL;
00498               rc = LDAP_SUCCESS;
00499        }
00500 
00501        if( rc == LDAP_SUCCESS ) {
00502               f->f_sub = op->o_tmpalloc( sizeof( ssa ), op->o_tmpmemctx );
00503               *f->f_sub = ssa;
00504        }
00505 
00506        Debug( LDAP_DEBUG_FILTER, "end get_ssa\n", 0, 0, 0 );
00507        return rc /* LDAP_SUCCESS */ ;
00508 }
00509 
00510 void
00511 filter_free_x( Operation *op, Filter *f, int freeme )
00512 {
00513        Filter *p, *next;
00514 
00515        if ( f == NULL ) {
00516               return;
00517        }
00518 
00519        f->f_choice &= SLAPD_FILTER_MASK;
00520 
00521        switch ( f->f_choice ) {
00522        case LDAP_FILTER_PRESENT:
00523               if ( f->f_desc->ad_flags & SLAP_DESC_TEMPORARY )
00524                      op->o_tmpfree( f->f_desc, op->o_tmpmemctx );
00525               break;
00526 
00527        case LDAP_FILTER_EQUALITY:
00528        case LDAP_FILTER_GE:
00529        case LDAP_FILTER_LE:
00530        case LDAP_FILTER_APPROX:
00531               ava_free( op, f->f_ava, 1 );
00532               break;
00533 
00534        case LDAP_FILTER_SUBSTRINGS:
00535               if ( f->f_sub_initial.bv_val != NULL ) {
00536                      op->o_tmpfree( f->f_sub_initial.bv_val, op->o_tmpmemctx );
00537               }
00538               ber_bvarray_free_x( f->f_sub_any, op->o_tmpmemctx );
00539               if ( f->f_sub_final.bv_val != NULL ) {
00540                      op->o_tmpfree( f->f_sub_final.bv_val, op->o_tmpmemctx );
00541               }
00542               if ( f->f_sub->sa_desc->ad_flags & SLAP_DESC_TEMPORARY )
00543                      op->o_tmpfree( f->f_sub->sa_desc, op->o_tmpmemctx );
00544               op->o_tmpfree( f->f_sub, op->o_tmpmemctx );
00545               break;
00546 
00547        case LDAP_FILTER_AND:
00548        case LDAP_FILTER_OR:
00549        case LDAP_FILTER_NOT:
00550               for ( p = f->f_list; p != NULL; p = next ) {
00551                      next = p->f_next;
00552                      filter_free_x( op, p, 1 );
00553               }
00554               break;
00555 
00556        case LDAP_FILTER_EXT:
00557               mra_free( op, f->f_mra, 1 );
00558               break;
00559 
00560        case SLAPD_FILTER_COMPUTED:
00561               break;
00562 
00563        default:
00564               Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
00565                      f->f_choice, 0, 0 );
00566               break;
00567        }
00568 
00569        if ( freeme ) {
00570               op->o_tmpfree( f, op->o_tmpmemctx );
00571        }
00572 }
00573 
00574 void
00575 filter_free( Filter *f )
00576 {
00577        Operation op;
00578        Opheader ohdr;
00579 
00580        op.o_hdr = &ohdr;
00581        op.o_tmpmemctx = slap_sl_context( f );
00582        op.o_tmpmfuncs = &slap_sl_mfuncs;
00583        filter_free_x( &op, f, 1 );
00584 }
00585 
00586 void
00587 filter2bv_x( Operation *op, Filter *f, struct berval *fstr )
00588 {
00589        filter2bv_undef_x( op, f, 0, fstr );
00590 }
00591 
00592 void
00593 filter2bv_undef_x( Operation *op, Filter *f, int noundef, struct berval *fstr )
00594 {
00595        int           i;
00596        Filter        *p;
00597        struct berval tmp, value;
00598        static struct berval
00599                      ber_bvfalse = BER_BVC( "(?=false)" ),
00600                      ber_bvtrue = BER_BVC( "(?=true)" ),
00601                      ber_bvundefined = BER_BVC( "(?=undefined)" ),
00602                      ber_bverror = BER_BVC( "(?=error)" ),
00603                      ber_bvunknown = BER_BVC( "(?=unknown)" ),
00604                      ber_bvnone = BER_BVC( "(?=none)" ),
00605                      ber_bvF = BER_BVC( "(|)" ),
00606                      ber_bvT = BER_BVC( "(&)" );
00607        ber_len_t     len;
00608        ber_tag_t     choice;
00609        int undef, undef2;
00610        char *sign;
00611 
00612        if ( f == NULL ) {
00613               ber_dupbv_x( fstr, &ber_bvnone, op->o_tmpmemctx );
00614               return;
00615        }
00616 
00617        undef = f->f_choice & SLAPD_FILTER_UNDEFINED;
00618        undef2 = (undef && !noundef);
00619        choice = f->f_choice & SLAPD_FILTER_MASK;
00620 
00621        switch ( choice ) {
00622        case LDAP_FILTER_EQUALITY:
00623               fstr->bv_len = STRLENOF("(=)");
00624               sign = "=";
00625               goto simple;
00626        case LDAP_FILTER_GE:
00627               fstr->bv_len = STRLENOF("(>=)");
00628               sign = ">=";
00629               goto simple;
00630        case LDAP_FILTER_LE:
00631               fstr->bv_len = STRLENOF("(<=)");
00632               sign = "<=";
00633               goto simple;
00634        case LDAP_FILTER_APPROX:
00635               fstr->bv_len = STRLENOF("(~=)");
00636               sign = "~=";
00637 
00638 simple:
00639               value = f->f_av_value;
00640               if ( f->f_av_desc->ad_type->sat_equality &&
00641                      !undef &&
00642                      ( f->f_av_desc->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))
00643               {
00644                      f->f_av_desc->ad_type->sat_equality->smr_normalize(
00645                             (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
00646                             NULL, NULL, &f->f_av_value, &value, op->o_tmpmemctx );
00647               }
00648 
00649               filter_escape_value_x( &value, &tmp, op->o_tmpmemctx );
00650               /* NOTE: tmp can legitimately be NULL (meaning empty) 
00651                * since in a Filter values in AVAs are supposed
00652                * to have been normalized, meaning that an empty value
00653                * is legal for that attribute's syntax */
00654 
00655               fstr->bv_len += f->f_av_desc->ad_cname.bv_len + tmp.bv_len;
00656               if ( undef2 )
00657                      fstr->bv_len++;
00658               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00659 
00660               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s)",
00661                      undef2 ? "?" : "",
00662                      f->f_av_desc->ad_cname.bv_val, sign,
00663                      tmp.bv_len ? tmp.bv_val : "" );
00664 
00665               if ( value.bv_val != f->f_av_value.bv_val ) {
00666                      ber_memfree_x( value.bv_val, op->o_tmpmemctx );
00667               }
00668 
00669               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
00670               break;
00671 
00672        case LDAP_FILTER_SUBSTRINGS:
00673               fstr->bv_len = f->f_sub_desc->ad_cname.bv_len +
00674                      STRLENOF("(=*)");
00675               if ( undef2 )
00676                      fstr->bv_len++;
00677               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
00678 
00679               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s=*)",
00680                      undef2 ? "?" : "",
00681                      f->f_sub_desc->ad_cname.bv_val );
00682 
00683               if ( f->f_sub_initial.bv_val != NULL ) {
00684                      ber_len_t tmplen;
00685 
00686                      len = fstr->bv_len;
00687 
00688                      filter_escape_value_x( &f->f_sub_initial, &tmp, op->o_tmpmemctx );
00689                      tmplen = tmp.bv_len;
00690 
00691                      fstr->bv_len += tmplen;
00692                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
00693                             fstr->bv_len + 1, op->o_tmpmemctx );
00694 
00695                      snprintf( &fstr->bv_val[len - 2],
00696                             tmplen + STRLENOF( /*(*/ "*)" ) + 1,
00697                             /* "(attr=" */ "%s*)",
00698                             tmp.bv_len ? tmp.bv_val : "");
00699 
00700                      ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
00701               }
00702 
00703               if ( f->f_sub_any != NULL ) {
00704                      for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
00705                             ber_len_t tmplen;
00706 
00707                             len = fstr->bv_len;
00708                             filter_escape_value_x( &f->f_sub_any[i],
00709                                    &tmp, op->o_tmpmemctx );
00710                             tmplen = tmp.bv_len;
00711 
00712                             fstr->bv_len += tmplen + STRLENOF( /*(*/ ")" );
00713                             fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
00714                                    fstr->bv_len + 1, op->o_tmpmemctx );
00715 
00716                             snprintf( &fstr->bv_val[len - 1],
00717                                    tmplen + STRLENOF( /*(*/ "*)" ) + 1,
00718                                    /* "(attr=[init]*[any*]" */ "%s*)",
00719                                    tmp.bv_len ? tmp.bv_val : "");
00720                             ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
00721                      }
00722               }
00723 
00724               if ( f->f_sub_final.bv_val != NULL ) {
00725                      ber_len_t tmplen;
00726 
00727                      len = fstr->bv_len;
00728 
00729                      filter_escape_value_x( &f->f_sub_final, &tmp, op->o_tmpmemctx );
00730                      tmplen = tmp.bv_len;
00731 
00732                      fstr->bv_len += tmplen;
00733                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
00734                             fstr->bv_len + 1, op->o_tmpmemctx );
00735 
00736                      snprintf( &fstr->bv_val[len - 1],
00737                             tmplen + STRLENOF( /*(*/ ")" ) + 1,
00738                             /* "(attr=[init*][any*]" */ "%s)",
00739                             tmp.bv_len ? tmp.bv_val : "");
00740 
00741                      ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
00742               }
00743 
00744               break;
00745 
00746        case LDAP_FILTER_PRESENT:
00747               fstr->bv_len = f->f_desc->ad_cname.bv_len +
00748                      STRLENOF("(=*)");
00749               if ( undef2 )
00750                      fstr->bv_len++;
00751 
00752               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00753 
00754               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s=*)",
00755                      undef2 ? "?" : "",
00756                      f->f_desc->ad_cname.bv_val );
00757               break;
00758 
00759        case LDAP_FILTER_AND:
00760        case LDAP_FILTER_OR:
00761        case LDAP_FILTER_NOT:
00762               fstr->bv_len = STRLENOF("(%)");
00763               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
00764 
00765               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
00766                      f->f_choice == LDAP_FILTER_AND ? '&' :
00767                      f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
00768 
00769               for ( p = f->f_list; p != NULL; p = p->f_next ) {
00770                      len = fstr->bv_len;
00771 
00772                      filter2bv_undef_x( op, p, noundef, &tmp );
00773                      
00774                      fstr->bv_len += tmp.bv_len;
00775                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
00776                             op->o_tmpmemctx );
00777 
00778                      snprintf( &fstr->bv_val[len-1],
00779                             tmp.bv_len + STRLENOF( /*(*/ ")" ) + 1, 
00780                             /*"("*/ "%s)", tmp.bv_val );
00781 
00782                      op->o_tmpfree( tmp.bv_val, op->o_tmpmemctx );
00783               }
00784 
00785               break;
00786 
00787        case LDAP_FILTER_EXT: {
00788               struct berval ad;
00789 
00790               filter_escape_value_x( &f->f_mr_value, &tmp, op->o_tmpmemctx );
00791               /* NOTE: tmp can legitimately be NULL (meaning empty) 
00792                * since in a Filter values in MRAs are supposed
00793                * to have been normalized, meaning that an empty value
00794                * is legal for that attribute's syntax */
00795 
00796               if ( f->f_mr_desc ) {
00797                      ad = f->f_mr_desc->ad_cname;
00798               } else {
00799                      ad.bv_len = 0;
00800                      ad.bv_val = "";
00801               }
00802               
00803               fstr->bv_len = ad.bv_len +
00804                      ( undef2 ? 1 : 0 ) +
00805                      ( f->f_mr_dnattrs ? STRLENOF(":dn") : 0 ) +
00806                      ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + STRLENOF(":") : 0 ) +
00807                      tmp.bv_len + STRLENOF("(:=)");
00808               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
00809 
00810               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s%s:=%s)",
00811                      undef2 ? "?" : "",
00812                      ad.bv_val,
00813                      f->f_mr_dnattrs ? ":dn" : "",
00814                      f->f_mr_rule_text.bv_len ? ":" : "",
00815                      f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
00816                      tmp.bv_len ? tmp.bv_val : "" );
00817               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
00818               } break;
00819 
00820        case SLAPD_FILTER_COMPUTED:
00821               switch ( f->f_result ) {
00822               case LDAP_COMPARE_FALSE:
00823                      tmp = ( noundef ? ber_bvF : ber_bvfalse );
00824                      break;
00825 
00826               case LDAP_COMPARE_TRUE:
00827                      tmp = ( noundef ? ber_bvT : ber_bvtrue );
00828                      break;
00829                      
00830               case SLAPD_COMPARE_UNDEFINED:
00831                      tmp = ber_bvundefined;
00832                      break;
00833                      
00834               default:
00835                      tmp = ber_bverror;
00836                      break;
00837               }
00838 
00839               ber_dupbv_x( fstr, &tmp, op->o_tmpmemctx );
00840               break;
00841               
00842        default:
00843               ber_dupbv_x( fstr, &ber_bvunknown, op->o_tmpmemctx );
00844               break;
00845        }
00846 }
00847 
00848 void
00849 filter2bv( Filter *f, struct berval *fstr )
00850 {
00851        filter2bv_undef( f, 0, fstr );
00852 }
00853 
00854 void
00855 filter2bv_undef( Filter *f, int noundef, struct berval *fstr )
00856 {
00857        Operation op;
00858        Opheader ohdr;
00859 
00860        op.o_hdr = &ohdr;
00861        op.o_tmpmemctx = NULL;
00862        op.o_tmpmfuncs = &ch_mfuncs;
00863 
00864        filter2bv_undef_x( &op, f, noundef, fstr );
00865 }
00866 
00867 Filter *
00868 filter_dup( Filter *f, void *memctx )
00869 {
00870        BerMemoryFunctions *mf = &slap_sl_mfuncs;
00871        Filter *n;
00872 
00873        if ( !f )
00874               return NULL;
00875 
00876        n = mf->bmf_malloc( sizeof(Filter), memctx );
00877        n->f_choice = f->f_choice;
00878        n->f_next = NULL;
00879 
00880        switch( f->f_choice & SLAPD_FILTER_MASK ) {
00881        case SLAPD_FILTER_COMPUTED:
00882               n->f_result = f->f_result;
00883               break;
00884        case LDAP_FILTER_PRESENT:
00885               if ( f->f_desc->ad_flags & SLAP_DESC_TEMPORARY )
00886                      n->f_desc = slap_bv2tmp_ad( &f->f_desc->ad_cname, memctx );
00887               else
00888                      n->f_desc = f->f_desc;
00889               break;
00890        case LDAP_FILTER_EQUALITY:
00891        case LDAP_FILTER_GE:
00892        case LDAP_FILTER_LE:
00893        case LDAP_FILTER_APPROX:
00894               /* Should this be ava_dup() ? */
00895               n->f_ava = mf->bmf_calloc( 1, sizeof(AttributeAssertion), memctx );
00896               *n->f_ava = *f->f_ava;
00897               if ( f->f_av_desc->ad_flags & SLAP_DESC_TEMPORARY )
00898                      n->f_av_desc = slap_bv2tmp_ad( &f->f_av_desc->ad_cname, memctx );
00899               ber_dupbv_x( &n->f_av_value, &f->f_av_value, memctx );
00900               break;
00901        case LDAP_FILTER_SUBSTRINGS:
00902               n->f_sub = mf->bmf_calloc( 1, sizeof(SubstringsAssertion), memctx );
00903               if ( f->f_sub_desc->ad_flags & SLAP_DESC_TEMPORARY )
00904                      n->f_sub_desc = slap_bv2tmp_ad( &f->f_sub_desc->ad_cname, memctx );
00905               else
00906                      n->f_sub_desc = f->f_sub_desc;
00907               if ( !BER_BVISNULL( &f->f_sub_initial ))
00908                      ber_dupbv_x( &n->f_sub_initial, &f->f_sub_initial, memctx );
00909               if ( f->f_sub_any ) {
00910                      int i;
00911                      for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ );
00912                      n->f_sub_any = mf->bmf_malloc(( i+1 )*sizeof( struct berval ),
00913                             memctx );
00914                      for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
00915                             ber_dupbv_x( &n->f_sub_any[i], &f->f_sub_any[i], memctx );
00916                      }
00917                      BER_BVZERO( &n->f_sub_any[i] );
00918               }
00919               if ( !BER_BVISNULL( &f->f_sub_final ))
00920                      ber_dupbv_x( &n->f_sub_final, &f->f_sub_final, memctx );
00921               break;
00922        case LDAP_FILTER_EXT: {
00923               /* Should this be mra_dup() ? */
00924               ber_len_t length;
00925               length = sizeof(MatchingRuleAssertion);
00926               if ( !BER_BVISNULL( &f->f_mr_rule_text ))
00927                      length += f->f_mr_rule_text.bv_len + 1;
00928               n->f_mra = mf->bmf_calloc( 1, length, memctx );
00929               *n->f_mra = *f->f_mra;
00930               if ( f->f_mr_desc && ( f->f_sub_desc->ad_flags & SLAP_DESC_TEMPORARY ))
00931                      n->f_mr_desc = slap_bv2tmp_ad( &f->f_mr_desc->ad_cname, memctx );
00932               ber_dupbv_x( &n->f_mr_value, &f->f_mr_value, memctx );
00933               if ( !BER_BVISNULL( &f->f_mr_rule_text )) {
00934                      n->f_mr_rule_text.bv_val = (char *)(n->f_mra+1);
00935                      AC_MEMCPY(n->f_mr_rule_text.bv_val,
00936                             f->f_mr_rule_text.bv_val, f->f_mr_rule_text.bv_len );
00937               }
00938               } break;
00939        case LDAP_FILTER_AND:
00940        case LDAP_FILTER_OR:
00941        case LDAP_FILTER_NOT: {
00942               Filter **p;
00943               for ( p = &n->f_list, f = f->f_list; f; f = f->f_next ) {
00944                      *p = filter_dup( f, memctx );
00945                      p = &(*p)->f_next;
00946               }
00947               } break;
00948        }
00949        return n;
00950 }
00951 
00952 static int
00953 get_simple_vrFilter(
00954        Operation *op,
00955        BerElement *ber,
00956        ValuesReturnFilter **filt,
00957        const char **text )
00958 {
00959        ber_tag_t     tag;
00960        ber_len_t     len;
00961        int           err;
00962        ValuesReturnFilter vrf;
00963 
00964        Debug( LDAP_DEBUG_FILTER, "begin get_simple_vrFilter\n", 0, 0, 0 );
00965 
00966        tag = ber_peek_tag( ber, &len );
00967 
00968        if( tag == LBER_ERROR ) {
00969               *text = "error decoding filter";
00970               return SLAPD_DISCONNECT;
00971        }
00972 
00973        vrf.vrf_next = NULL;
00974 
00975        err = LDAP_SUCCESS;
00976        vrf.vrf_choice = tag; 
00977 
00978        switch ( vrf.vrf_choice ) {
00979        case LDAP_FILTER_EQUALITY:
00980               Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
00981               err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_EQUALITY, text );
00982               if ( err != LDAP_SUCCESS ) {
00983                      break;
00984               }
00985 
00986               assert( vrf.vrf_ava != NULL );
00987               break;
00988 
00989        case LDAP_FILTER_SUBSTRINGS:
00990               Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
00991               err = get_ssa( op, ber, (Filter *)&vrf, text );
00992               break;
00993 
00994        case LDAP_FILTER_GE:
00995               Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
00996               err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_ORDERING, text );
00997               if ( err != LDAP_SUCCESS ) {
00998                      break;
00999               }
01000               break;
01001 
01002        case LDAP_FILTER_LE:
01003               Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
01004               err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_ORDERING, text );
01005               if ( err != LDAP_SUCCESS ) {
01006                      break;
01007               }
01008               break;
01009 
01010        case LDAP_FILTER_PRESENT: {
01011               struct berval type;
01012 
01013               Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
01014               if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
01015                      err = SLAPD_DISCONNECT;
01016                      *text = "error decoding filter";
01017                      break;
01018               }
01019 
01020               vrf.vrf_desc = NULL;
01021               err = slap_bv2ad( &type, &vrf.vrf_desc, text );
01022 
01023               if( err != LDAP_SUCCESS ) {
01024                      vrf.vrf_choice |= SLAPD_FILTER_UNDEFINED;
01025                      err = slap_bv2undef_ad( &type, &vrf.vrf_desc, text,
01026                             SLAP_AD_PROXIED);
01027 
01028                      if( err != LDAP_SUCCESS ) {
01029                             /* unrecognized attribute description or other error */
01030                             Debug( LDAP_DEBUG_ANY, 
01031                                    "get_simple_vrFilter: conn %lu unknown "
01032                                    "attribute type=%s (%d)\n",
01033                                    op->o_connid, type.bv_val, err );
01034        
01035                             vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
01036                             vrf.vrf_result = LDAP_COMPARE_FALSE;
01037                             err = LDAP_SUCCESS;
01038                             break;
01039                      }
01040               }
01041               } break;
01042 
01043        case LDAP_FILTER_APPROX:
01044               Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
01045               err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_EQUALITY_APPROX, text );
01046               if ( err != LDAP_SUCCESS ) {
01047                      break;
01048               }
01049               break;
01050 
01051        case LDAP_FILTER_EXT:
01052               Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
01053 
01054               err = get_mra( op, ber, (Filter *)&vrf, text );
01055               if ( err != LDAP_SUCCESS ) {
01056                      break;
01057               }
01058 
01059               assert( vrf.vrf_mra != NULL );
01060               break;
01061 
01062        default:
01063               (void) ber_scanf( ber, "x" ); /* skip the element */
01064               Debug( LDAP_DEBUG_ANY, "get_simple_vrFilter: unknown filter type=%lu\n",
01065                      vrf.vrf_choice, 0, 0 );
01066               vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
01067               vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
01068               break;
01069        }
01070 
01071        if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
01072               /* ignore error */
01073               vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
01074               vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
01075               err = LDAP_SUCCESS;
01076        }
01077 
01078        if ( err == LDAP_SUCCESS ) {
01079               *filt = op->o_tmpalloc( sizeof vrf, op->o_tmpmemctx );
01080               **filt = vrf;
01081        }
01082 
01083        Debug( LDAP_DEBUG_FILTER, "end get_simple_vrFilter %d\n", err, 0, 0 );
01084 
01085        return err;
01086 }
01087 
01088 int
01089 get_vrFilter( Operation *op, BerElement *ber,
01090        ValuesReturnFilter **vrf,
01091        const char **text )
01092 {
01093        /*
01094         * A ValuesReturnFilter looks like this:
01095         *
01096         *     ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
01097         *      SimpleFilterItem ::= CHOICE {
01098         *              equalityMatch   [3]     AttributeValueAssertion,
01099         *              substrings      [4]     SubstringFilter,
01100         *              greaterOrEqual  [5]     AttributeValueAssertion,
01101         *              lessOrEqual     [6]     AttributeValueAssertion,
01102         *              present         [7]     AttributeType,
01103         *              approxMatch     [8]     AttributeValueAssertion,
01104         *            extensibleMatch [9]  SimpleMatchingAssertion -- LDAPv3
01105         *      }
01106         *
01107         *      SubstringFilter ::= SEQUENCE {
01108         *              type               AttributeType,
01109         *              SEQUENCE OF CHOICE {
01110         *                      initial          [0] IA5String,
01111         *                      any              [1] IA5String,
01112         *                      final            [2] IA5String
01113         *              }
01114         *      }
01115         *
01116         *     SimpleMatchingAssertion ::= SEQUENCE {    -- LDAPv3
01117         *            matchingRule    [1] MatchingRuleId OPTIONAL,
01118         *            type            [2] AttributeDescription OPTIONAL,
01119         *            matchValue      [3] AssertionValue }
01120         */
01121 
01122        ValuesReturnFilter **n;
01123        ber_tag_t     tag;
01124        ber_len_t     len;
01125        char          *last;
01126 
01127        Debug( LDAP_DEBUG_FILTER, "begin get_vrFilter\n", 0, 0, 0 );
01128 
01129        tag = ber_peek_tag( ber, &len );
01130 
01131        if( tag == LBER_ERROR ) {
01132               *text = "error decoding vrFilter";
01133               return SLAPD_DISCONNECT;
01134        }
01135 
01136        if( tag != LBER_SEQUENCE ) {
01137               *text = "error decoding vrFilter, expect SEQUENCE tag";
01138               return SLAPD_DISCONNECT;
01139        }
01140 
01141        n = vrf;
01142        for ( tag = ber_first_element( ber, &len, &last );
01143               tag != LBER_DEFAULT;
01144               tag = ber_next_element( ber, &len, last ) )
01145        {
01146               int err = get_simple_vrFilter( op, ber, n, text );
01147 
01148               if ( err != LDAP_SUCCESS ) return( err );
01149 
01150               n = &(*n)->vrf_next;
01151        }
01152        *n = NULL;
01153 
01154        Debug( LDAP_DEBUG_FILTER, "end get_vrFilter\n", 0, 0, 0 );
01155        return( LDAP_SUCCESS );
01156 }
01157 
01158 void
01159 vrFilter_free( Operation *op, ValuesReturnFilter *vrf )
01160 {
01161        ValuesReturnFilter   *p, *next;
01162 
01163        if ( vrf == NULL ) {
01164               return;
01165        }
01166 
01167        for ( p = vrf; p != NULL; p = next ) {
01168               next = p->vrf_next;
01169 
01170               switch ( vrf->vrf_choice & SLAPD_FILTER_MASK ) {
01171               case LDAP_FILTER_PRESENT:
01172                      break;
01173 
01174               case LDAP_FILTER_EQUALITY:
01175               case LDAP_FILTER_GE:
01176               case LDAP_FILTER_LE:
01177               case LDAP_FILTER_APPROX:
01178                      ava_free( op, vrf->vrf_ava, 1 );
01179                      break;
01180 
01181               case LDAP_FILTER_SUBSTRINGS:
01182                      if ( vrf->vrf_sub_initial.bv_val != NULL ) {
01183                             op->o_tmpfree( vrf->vrf_sub_initial.bv_val, op->o_tmpmemctx );
01184                      }
01185                      ber_bvarray_free_x( vrf->vrf_sub_any, op->o_tmpmemctx );
01186                      if ( vrf->vrf_sub_final.bv_val != NULL ) {
01187                             op->o_tmpfree( vrf->vrf_sub_final.bv_val, op->o_tmpmemctx );
01188                      }
01189                      op->o_tmpfree( vrf->vrf_sub, op->o_tmpmemctx );
01190                      break;
01191 
01192               case LDAP_FILTER_EXT:
01193                      mra_free( op, vrf->vrf_mra, 1 );
01194                      break;
01195 
01196               case SLAPD_FILTER_COMPUTED:
01197                      break;
01198 
01199               default:
01200                      Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
01201                             vrf->vrf_choice, 0, 0 );
01202                      break;
01203               }
01204 
01205               op->o_tmpfree( vrf, op->o_tmpmemctx );
01206        }
01207 }
01208 
01209 void
01210 vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
01211 {
01212        ValuesReturnFilter   *p;
01213        struct berval tmp;
01214        ber_len_t len;
01215 
01216        if ( vrf == NULL ) {
01217               ber_str2bv_x( "No filter!", STRLENOF("No filter!"),
01218                      1, fstr, op->o_tmpmemctx );
01219               return;
01220        }
01221 
01222        fstr->bv_len = STRLENOF("()");
01223        fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
01224 
01225        snprintf( fstr->bv_val, fstr->bv_len + 1, "()");
01226 
01227        for ( p = vrf; p != NULL; p = p->vrf_next ) {
01228               len = fstr->bv_len;
01229 
01230               simple_vrFilter2bv( op, p, &tmp );
01231                      
01232               fstr->bv_len += tmp.bv_len;
01233               fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
01234                      op->o_tmpmemctx );
01235 
01236               snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2, 
01237                      /*"("*/ "%s)", tmp.bv_val );
01238 
01239               op->o_tmpfree( tmp.bv_val, op->o_tmpmemctx );
01240        }
01241 }
01242 
01243 static void
01244 simple_vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
01245 {
01246        struct berval tmp;
01247        ber_len_t len;
01248        int undef;
01249 
01250        if ( vrf == NULL ) {
01251               ber_str2bv_x( "No filter!", STRLENOF("No filter!"), 1, fstr,
01252                      op->o_tmpmemctx );
01253               return;
01254        }
01255        undef = vrf->vrf_choice & SLAPD_FILTER_UNDEFINED;
01256 
01257        switch ( vrf->vrf_choice & SLAPD_FILTER_MASK ) {
01258        case LDAP_FILTER_EQUALITY:
01259               filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
01260 
01261               fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
01262                      tmp.bv_len + STRLENOF("(=)");
01263               if ( undef ) fstr->bv_len++;
01264               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
01265 
01266               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
01267                      vrf->vrf_av_desc->ad_cname.bv_val,
01268                      tmp.bv_val );
01269 
01270               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01271               break;
01272 
01273        case LDAP_FILTER_GE:
01274               filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
01275 
01276               fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
01277                      tmp.bv_len + STRLENOF("(>=)");
01278               if ( undef ) fstr->bv_len++;
01279               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
01280 
01281               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
01282                      vrf->vrf_av_desc->ad_cname.bv_val,
01283                      tmp.bv_val );
01284 
01285               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01286               break;
01287 
01288        case LDAP_FILTER_LE:
01289               filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
01290 
01291               fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
01292                      tmp.bv_len + STRLENOF("(<=)");
01293               if ( undef ) fstr->bv_len++;
01294               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
01295 
01296               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
01297                      vrf->vrf_av_desc->ad_cname.bv_val,
01298                      tmp.bv_val );
01299 
01300               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01301               break;
01302 
01303        case LDAP_FILTER_APPROX:
01304               filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
01305 
01306               fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
01307                      tmp.bv_len + STRLENOF("(~=)");
01308               if ( undef ) fstr->bv_len++;
01309               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
01310 
01311               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
01312                      vrf->vrf_av_desc->ad_cname.bv_val,
01313                      tmp.bv_val );
01314               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01315               break;
01316 
01317        case LDAP_FILTER_SUBSTRINGS:
01318               fstr->bv_len = vrf->vrf_sub_desc->ad_cname.bv_len +
01319                      STRLENOF("(=*)");
01320               if ( undef ) fstr->bv_len++;
01321               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
01322 
01323               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
01324                      vrf->vrf_sub_desc->ad_cname.bv_val );
01325 
01326               if ( vrf->vrf_sub_initial.bv_val != NULL ) {
01327                      len = fstr->bv_len;
01328 
01329                      filter_escape_value_x( &vrf->vrf_sub_initial, &tmp, op->o_tmpmemctx );
01330 
01331                      fstr->bv_len += tmp.bv_len;
01332                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
01333                             op->o_tmpmemctx );
01334 
01335                      snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
01336                             /* "(attr=" */ "%s*)",
01337                             tmp.bv_val );
01338 
01339                      ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01340               }
01341 
01342               if ( vrf->vrf_sub_any != NULL ) {
01343                      int i;
01344                      for ( i = 0; vrf->vrf_sub_any[i].bv_val != NULL; i++ ) {
01345                             len = fstr->bv_len;
01346                             filter_escape_value_x( &vrf->vrf_sub_any[i], &tmp,
01347                                    op->o_tmpmemctx );
01348 
01349                             fstr->bv_len += tmp.bv_len + 1;
01350                             fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
01351                                    fstr->bv_len + 1, op->o_tmpmemctx );
01352 
01353                             snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
01354                                    /* "(attr=[init]*[any*]" */ "%s*)",
01355                                    tmp.bv_val );
01356                             ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01357                      }
01358               }
01359 
01360               if ( vrf->vrf_sub_final.bv_val != NULL ) {
01361                      len = fstr->bv_len;
01362 
01363                      filter_escape_value_x( &vrf->vrf_sub_final, &tmp, op->o_tmpmemctx );
01364 
01365                      fstr->bv_len += tmp.bv_len;
01366                      fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
01367                             op->o_tmpmemctx );
01368 
01369                      snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
01370                             /* "(attr=[init*][any*]" */ "%s)",
01371                             tmp.bv_val );
01372 
01373                      ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01374               }
01375 
01376               break;
01377 
01378        case LDAP_FILTER_PRESENT:
01379               fstr->bv_len = vrf->vrf_desc->ad_cname.bv_len +
01380                      STRLENOF("(=*)");
01381               if ( undef ) fstr->bv_len++;
01382               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
01383 
01384               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
01385                      vrf->vrf_desc->ad_cname.bv_val );
01386               break;
01387 
01388        case LDAP_FILTER_EXT: {
01389               struct berval ad;
01390               filter_escape_value_x( &vrf->vrf_mr_value, &tmp, op->o_tmpmemctx );
01391 
01392               if ( vrf->vrf_mr_desc ) {
01393                      ad = vrf->vrf_mr_desc->ad_cname;
01394               } else {
01395                      ad.bv_len = 0;
01396                      ad.bv_val = "";
01397               }
01398                      
01399               fstr->bv_len = ad.bv_len +
01400                      ( vrf->vrf_mr_dnattrs ? STRLENOF(":dn") : 0 ) +
01401                      ( vrf->vrf_mr_rule_text.bv_len
01402                             ? vrf->vrf_mr_rule_text.bv_len+1 : 0 ) +
01403                      tmp.bv_len + STRLENOF("(:=)");
01404               if ( undef ) fstr->bv_len++;
01405               fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
01406 
01407               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
01408                      ad.bv_val,
01409                      vrf->vrf_mr_dnattrs ? ":dn" : "",
01410                      vrf->vrf_mr_rule_text.bv_len ? ":" : "",
01411                      vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_val : "",
01412                      tmp.bv_val );
01413 
01414               ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
01415               } break;
01416 
01417        case SLAPD_FILTER_COMPUTED:
01418               ber_str2bv_x(
01419                      vrf->vrf_result == LDAP_COMPARE_FALSE ? "(?=false)" :
01420                      vrf->vrf_result == LDAP_COMPARE_TRUE ? "(?=true)" :
01421                      vrf->vrf_result == SLAPD_COMPARE_UNDEFINED
01422                             ? "(?=undefined)" : "(?=error)",
01423                      vrf->vrf_result == LDAP_COMPARE_FALSE ? STRLENOF("(?=false)") :
01424                      vrf->vrf_result == LDAP_COMPARE_TRUE ? STRLENOF("(?=true)") :
01425                      vrf->vrf_result == SLAPD_COMPARE_UNDEFINED
01426                             ? STRLENOF("(?=undefined)") : STRLENOF("(?=error)"),
01427                      1, fstr, op->o_tmpmemctx );
01428               break;
01429 
01430        default:
01431               ber_str2bv_x( "(?=unknown)", STRLENOF("(?=unknown)"),
01432                      1, fstr, op->o_tmpmemctx );
01433               break;
01434        }
01435 }