Back to index

openldap  2.4.31
map.c
Go to the documentation of this file.
00001 /* map.c - ldap backend mapping routines */
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 /* ACKNOWLEDGEMENTS:
00017  * This work was initially developed by the Howard Chu for inclusion
00018  * in OpenLDAP Software and subsequently enhanced by Pierangelo
00019  * Masarati.
00020  */
00021 /* This is an altered version */
00022 /*
00023  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
00024  * 
00025  * Permission is granted to anyone to use this software for any purpose
00026  * on any computer system, and to alter it and redistribute it, subject
00027  * to the following restrictions:
00028  * 
00029  * 1. The author is not responsible for the consequences of use of this
00030  *    software, no matter how awful, even if they arise from flaws in it.
00031  * 
00032  * 2. The origin of this software must not be misrepresented, either by
00033  *    explicit claim or by omission.  Since few users ever read sources,
00034  *    credits should appear in the documentation.
00035  * 
00036  * 3. Altered versions must be plainly marked as such, and must not be
00037  *    misrepresented as being the original software.  Since few users
00038  *    ever read sources, credits should appear in the documentation.
00039  * 
00040  * 4. This notice may not be removed or altered.
00041  *
00042  *
00043  *
00044  * Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
00045  * 
00046  * This software is being modified by Pierangelo Masarati.
00047  * The previously reported conditions apply to the modified code as well.
00048  * Changes in the original code are highlighted where required.
00049  * Credits for the original code go to the author, Howard Chu.
00050  */
00051 
00052 #include "portable.h"
00053 
00054 #include <stdio.h>
00055 
00056 #include <ac/string.h>
00057 #include <ac/socket.h>
00058 
00059 #include "slap.h"
00060 #include "lutil.h"
00061 #include "../back-ldap/back-ldap.h"
00062 #include "back-meta.h"
00063 
00064 int
00065 mapping_cmp ( const void *c1, const void *c2 )
00066 {
00067        struct ldapmapping *map1 = (struct ldapmapping *)c1;
00068        struct ldapmapping *map2 = (struct ldapmapping *)c2;
00069        int rc = map1->src.bv_len - map2->src.bv_len;
00070        if (rc) return rc;
00071        return ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) );
00072 }
00073 
00074 int
00075 mapping_dup ( void *c1, void *c2 )
00076 {
00077        struct ldapmapping *map1 = (struct ldapmapping *)c1;
00078        struct ldapmapping *map2 = (struct ldapmapping *)c2;
00079 
00080        return ( ( strcasecmp( map1->src.bv_val, map2->src.bv_val ) == 0 ) ? -1 : 0 );
00081 }
00082 
00083 void
00084 ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
00085 {
00086        struct ldapmapping *mapping;
00087 
00088        assert( m != NULL );
00089 
00090        *m = NULL;
00091 
00092        mapping = (struct ldapmapping *)ch_calloc( 2, 
00093                      sizeof( struct ldapmapping ) );
00094        if ( mapping == NULL ) {
00095               return;
00096        }
00097 
00098        ber_str2bv( "objectclass", STRLENOF("objectclass"), 1, &mapping[0].src);
00099        ber_dupbv( &mapping[0].dst, &mapping[0].src );
00100        mapping[1].src = mapping[0].src;
00101        mapping[1].dst = mapping[0].dst;
00102 
00103        avl_insert( &lm->map, (caddr_t)&mapping[0], 
00104                      mapping_cmp, mapping_dup );
00105        avl_insert( &lm->remap, (caddr_t)&mapping[1], 
00106                      mapping_cmp, mapping_dup );
00107        *m = mapping;
00108 }
00109 
00110 int
00111 ldap_back_mapping ( struct ldapmap *map, struct berval *s, struct ldapmapping **m,
00112        int remap )
00113 {
00114        Avlnode *tree;
00115        struct ldapmapping fmapping;
00116 
00117        assert( m != NULL );
00118 
00119        /* let special attrnames slip through (ITS#5760) */
00120        if ( bvmatch( s, slap_bv_no_attrs )
00121               || bvmatch( s, slap_bv_all_user_attrs )
00122               || bvmatch( s, slap_bv_all_operational_attrs ) )
00123        {
00124               *m = NULL;
00125               return 0;
00126        }
00127 
00128        if ( remap == BACKLDAP_REMAP ) {
00129               tree = map->remap;
00130 
00131        } else {
00132               tree = map->map;
00133        }
00134 
00135        fmapping.src = *s;
00136        *m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping, mapping_cmp );
00137        if ( *m == NULL ) {
00138               return map->drop_missing;
00139        }
00140 
00141        return 0;
00142 }
00143 
00144 void
00145 ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
00146        int remap )
00147 {
00148        struct ldapmapping *mapping;
00149        int drop_missing;
00150 
00151        /* map->map may be NULL when mapping is configured,
00152         * but map->remap can't */
00153        if ( map->remap == NULL ) {
00154               *bv = *s;
00155               return;
00156        }
00157 
00158        BER_BVZERO( bv );
00159        drop_missing = ldap_back_mapping( map, s, &mapping, remap );
00160        if ( mapping != NULL ) {
00161               if ( !BER_BVISNULL( &mapping->dst ) ) {
00162                      *bv = mapping->dst;
00163               }
00164               return;
00165        }
00166 
00167        if ( !drop_missing ) {
00168               *bv = *s;
00169        }
00170 }
00171 
00172 int
00173 ldap_back_map_attrs(
00174               Operation *op,
00175               struct ldapmap *at_map,
00176               AttributeName *an,
00177               int remap,
00178               char ***mapped_attrs )
00179 {
00180        int i, x, j;
00181        char **na;
00182        struct berval mapped;
00183 
00184        if ( an == NULL && op->o_bd->be_extra_anlist == NULL ) {
00185               *mapped_attrs = NULL;
00186               return LDAP_SUCCESS;
00187        }
00188 
00189        i = 0;
00190        if ( an != NULL ) {
00191               for ( ; !BER_BVISNULL( &an[i].an_name ); i++ )
00192                      /*  */ ;
00193        }
00194 
00195        x = 0;
00196        if ( op->o_bd->be_extra_anlist != NULL ) {
00197               for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
00198                      /*  */ ;
00199        }
00200 
00201        assert( i > 0 || x > 0 );
00202        
00203        na = (char **)ber_memcalloc_x( i + x + 1, sizeof(char *), op->o_tmpmemctx );
00204        if ( na == NULL ) {
00205               *mapped_attrs = NULL;
00206               return LDAP_NO_MEMORY;
00207        }
00208 
00209        j = 0;
00210        if ( i > 0 ) {
00211               for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
00212                      ldap_back_map( at_map, &an[i].an_name, &mapped, remap );
00213                      if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) {
00214                             na[j++] = mapped.bv_val;
00215                      }
00216               }
00217        }
00218 
00219        if ( x > 0 ) {
00220               for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) {
00221                      if ( op->o_bd->be_extra_anlist[x].an_desc &&
00222                             ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, an ) )
00223                      {
00224                             continue;
00225                      }
00226 
00227                      ldap_back_map( at_map, &op->o_bd->be_extra_anlist[x].an_name, &mapped, remap );
00228                      if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) {
00229                             na[j++] = mapped.bv_val;
00230                      }
00231               }
00232        }
00233 
00234        if ( j == 0 && ( i > 0 || x > 0 ) ) {
00235               na[j++] = LDAP_NO_ATTRS;
00236        }
00237        na[j] = NULL;
00238 
00239        *mapped_attrs = na;
00240 
00241        return LDAP_SUCCESS;
00242 }
00243 
00244 static int
00245 map_attr_value(
00246               dncookie             *dc,
00247               AttributeDescription        *ad,
00248               struct berval        *mapped_attr,
00249               struct berval        *value,
00250               struct berval        *mapped_value,
00251               int                  remap,
00252               void                 *memctx )
00253 {
00254        struct berval        vtmp;
00255        int                  freeval = 0;
00256 
00257        ldap_back_map( &dc->target->mt_rwmap.rwm_at, &ad->ad_cname, mapped_attr, remap );
00258        if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) {
00259 #if 0
00260               /*
00261                * FIXME: are we sure we need to search oc_map if at_map fails?
00262                */
00263               ldap_back_map( &dc->target->mt_rwmap.rwm_oc, &ad->ad_cname, mapped_attr, remap );
00264               if ( BER_BVISNULL( mapped_attr ) || BER_BVISEMPTY( mapped_attr ) ) {
00265                      *mapped_attr = ad->ad_cname;
00266               }
00267 #endif
00268               if ( dc->target->mt_rwmap.rwm_at.drop_missing ) {
00269                      return -1;
00270               }
00271 
00272               *mapped_attr = ad->ad_cname;
00273        }
00274 
00275        if ( value == NULL ) {
00276               return 0;
00277        }
00278 
00279        if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
00280        {
00281               dncookie fdc = *dc;
00282 
00283 #ifdef ENABLE_REWRITE
00284               fdc.ctx = "searchFilterAttrDN";
00285 #endif
00286 
00287               switch ( ldap_back_dn_massage( &fdc, value, &vtmp ) ) {
00288               case LDAP_SUCCESS:
00289                      if ( vtmp.bv_val != value->bv_val ) {
00290                             freeval = 1;
00291                      }
00292                      break;
00293               
00294               case LDAP_UNWILLING_TO_PERFORM:
00295                      return -1;
00296 
00297               case LDAP_OTHER:
00298                      return -1;
00299               }
00300 
00301        } else if ( ad->ad_type->sat_equality && 
00302               ad->ad_type->sat_equality->smr_usage & SLAP_MR_MUTATION_NORMALIZER )
00303        {
00304               if ( ad->ad_type->sat_equality->smr_normalize(
00305                      (SLAP_MR_DENORMALIZE|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX),
00306                      NULL, NULL, value, &vtmp, memctx ) )
00307               {
00308                      return -1;
00309               }
00310               freeval = 2;
00311 
00312        } else if ( ad == slap_schema.si_ad_objectClass || ad == slap_schema.si_ad_structuralObjectClass ) {
00313               ldap_back_map( &dc->target->mt_rwmap.rwm_oc, value, &vtmp, remap );
00314               if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
00315                      vtmp = *value;
00316               }
00317               
00318        } else {
00319               vtmp = *value;
00320        }
00321 
00322        filter_escape_value_x( &vtmp, mapped_value, memctx );
00323 
00324        switch ( freeval ) {
00325        case 1:
00326               ber_memfree( vtmp.bv_val );
00327               break;
00328        case 2:
00329               ber_memfree_x( vtmp.bv_val, memctx );
00330               break;
00331        }
00332        
00333        return 0;
00334 }
00335 
00336 static int
00337 ldap_back_int_filter_map_rewrite(
00338               dncookie             *dc,
00339               Filter               *f,
00340               struct berval *fstr,
00341               int                         remap,
00342               void                 *memctx )
00343 {
00344        int           i;
00345        Filter        *p;
00346        struct berval atmp,
00347                      vtmp,
00348                      *tmp;
00349        static struct berval
00350                      /* better than nothing... */
00351                      ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
00352                      ber_bvtf_false = BER_BVC( "(|)" ),
00353                      /* better than nothing... */
00354                      ber_bvtrue = BER_BVC( "(objectClass=*)" ),
00355                      ber_bvtf_true = BER_BVC( "(&)" ),
00356 #if 0
00357                      /* no longer needed; preserved for completeness */
00358                      ber_bvundefined = BER_BVC( "(?=undefined)" ),
00359 #endif
00360                      ber_bverror = BER_BVC( "(?=error)" ),
00361                      ber_bvunknown = BER_BVC( "(?=unknown)" ),
00362                      ber_bvnone = BER_BVC( "(?=none)" );
00363        ber_len_t     len;
00364 
00365        assert( fstr != NULL );
00366        BER_BVZERO( fstr );
00367 
00368        if ( f == NULL ) {
00369               ber_dupbv_x( fstr, &ber_bvnone, memctx );
00370               return LDAP_OTHER;
00371        }
00372 
00373        switch ( ( f->f_choice & SLAPD_FILTER_MASK ) ) {
00374        case LDAP_FILTER_EQUALITY:
00375               if ( map_attr_value( dc, f->f_av_desc, &atmp,
00376                                    &f->f_av_value, &vtmp, remap, memctx ) )
00377               {
00378                      goto computed;
00379               }
00380 
00381               fstr->bv_len = atmp.bv_len + vtmp.bv_len
00382                      + ( sizeof("(=)") - 1 );
00383               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
00384 
00385               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
00386                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00387 
00388               ber_memfree_x( vtmp.bv_val, memctx );
00389               break;
00390 
00391        case LDAP_FILTER_GE:
00392               if ( map_attr_value( dc, f->f_av_desc, &atmp,
00393                                    &f->f_av_value, &vtmp, remap, memctx ) )
00394               {
00395                      goto computed;
00396               }
00397 
00398               fstr->bv_len = atmp.bv_len + vtmp.bv_len
00399                      + ( sizeof("(>=)") - 1 );
00400               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
00401 
00402               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
00403                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00404 
00405               ber_memfree_x( vtmp.bv_val, memctx );
00406               break;
00407 
00408        case LDAP_FILTER_LE:
00409               if ( map_attr_value( dc, f->f_av_desc, &atmp,
00410                                    &f->f_av_value, &vtmp, remap, memctx ) )
00411               {
00412                      goto computed;
00413               }
00414 
00415               fstr->bv_len = atmp.bv_len + vtmp.bv_len
00416                      + ( sizeof("(<=)") - 1 );
00417               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
00418 
00419               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
00420                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00421 
00422               ber_memfree_x( vtmp.bv_val, memctx );
00423               break;
00424 
00425        case LDAP_FILTER_APPROX:
00426               if ( map_attr_value( dc, f->f_av_desc, &atmp,
00427                                    &f->f_av_value, &vtmp, remap, memctx ) )
00428               {
00429                      goto computed;
00430               }
00431 
00432               fstr->bv_len = atmp.bv_len + vtmp.bv_len
00433                      + ( sizeof("(~=)") - 1 );
00434               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
00435 
00436               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
00437                      atmp.bv_val, vtmp.bv_len ? vtmp.bv_val : "" );
00438 
00439               ber_memfree_x( vtmp.bv_val, memctx );
00440               break;
00441 
00442        case LDAP_FILTER_SUBSTRINGS:
00443               if ( map_attr_value( dc, f->f_sub_desc, &atmp,
00444                                    NULL, NULL, remap, memctx ) )
00445               {
00446                      goto computed;
00447               }
00448 
00449               /* cannot be a DN ... */
00450 
00451               fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) );
00452               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx ); /* FIXME: why 128 ? */
00453 
00454               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
00455                      atmp.bv_val );
00456 
00457               if ( !BER_BVISNULL( &f->f_sub_initial ) ) {
00458                      len = fstr->bv_len;
00459 
00460                      filter_escape_value_x( &f->f_sub_initial, &vtmp, memctx );
00461 
00462                      fstr->bv_len += vtmp.bv_len;
00463                      fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
00464 
00465                      snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
00466                             /* "(attr=" */ "%s*)",
00467                             vtmp.bv_len ? vtmp.bv_val : "" );
00468 
00469                      ber_memfree_x( vtmp.bv_val, memctx );
00470               }
00471 
00472               if ( f->f_sub_any != NULL ) {
00473                      for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
00474                             len = fstr->bv_len;
00475                             filter_escape_value_x( &f->f_sub_any[i], &vtmp, memctx );
00476 
00477                             fstr->bv_len += vtmp.bv_len + 1;
00478                             fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
00479 
00480                             snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
00481                                    /* "(attr=[init]*[any*]" */ "%s*)",
00482                                    vtmp.bv_len ? vtmp.bv_val : "" );
00483                             ber_memfree_x( vtmp.bv_val, memctx );
00484                      }
00485               }
00486 
00487               if ( !BER_BVISNULL( &f->f_sub_final ) ) {
00488                      len = fstr->bv_len;
00489 
00490                      filter_escape_value_x( &f->f_sub_final, &vtmp, memctx );
00491 
00492                      fstr->bv_len += vtmp.bv_len;
00493                      fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
00494 
00495                      snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
00496                             /* "(attr=[init*][any*]" */ "%s)",
00497                             vtmp.bv_len ? vtmp.bv_val : "" );
00498 
00499                      ber_memfree_x( vtmp.bv_val, memctx );
00500               }
00501 
00502               break;
00503 
00504        case LDAP_FILTER_PRESENT:
00505               if ( map_attr_value( dc, f->f_desc, &atmp,
00506                                    NULL, NULL, remap, memctx ) )
00507               {
00508                      goto computed;
00509               }
00510 
00511               fstr->bv_len = atmp.bv_len + ( STRLENOF( "(=*)" ) );
00512               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
00513 
00514               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
00515                      atmp.bv_val );
00516               break;
00517 
00518        case LDAP_FILTER_AND:
00519        case LDAP_FILTER_OR:
00520        case LDAP_FILTER_NOT:
00521               fstr->bv_len = STRLENOF( "(%)" );
00522               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 128, memctx );   /* FIXME: why 128? */
00523 
00524               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
00525                      f->f_choice == LDAP_FILTER_AND ? '&' :
00526                      f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
00527 
00528               for ( p = f->f_list; p != NULL; p = p->f_next ) {
00529                      int    rc;
00530 
00531                      len = fstr->bv_len;
00532 
00533                      rc = ldap_back_int_filter_map_rewrite( dc, p, &vtmp, remap, memctx );
00534                      if ( rc != LDAP_SUCCESS ) {
00535                             return rc;
00536                      }
00537                      
00538                      fstr->bv_len += vtmp.bv_len;
00539                      fstr->bv_val = ber_memrealloc_x( fstr->bv_val, fstr->bv_len + 1, memctx );
00540 
00541                      snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2, 
00542                             /*"("*/ "%s)", vtmp.bv_len ? vtmp.bv_val : "" );
00543 
00544                      ber_memfree_x( vtmp.bv_val, memctx );
00545               }
00546 
00547               break;
00548 
00549        case LDAP_FILTER_EXT:
00550               if ( f->f_mr_desc ) {
00551                      if ( map_attr_value( dc, f->f_mr_desc, &atmp,
00552                                           &f->f_mr_value, &vtmp, remap, memctx ) )
00553                      {
00554                             goto computed;
00555                      }
00556 
00557               } else {
00558                      BER_BVSTR( &atmp, "" );
00559                      filter_escape_value_x( &f->f_mr_value, &vtmp, memctx );
00560               }
00561 
00562               /* FIXME: cleanup (less ?: operators...) */
00563               fstr->bv_len = atmp.bv_len +
00564                      ( f->f_mr_dnattrs ? STRLENOF( ":dn" ) : 0 ) +
00565                      ( !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
00566                      vtmp.bv_len + ( STRLENOF( "(:=)" ) );
00567               fstr->bv_val = ber_memalloc_x( fstr->bv_len + 1, memctx );
00568 
00569               snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
00570                      atmp.bv_val,
00571                      f->f_mr_dnattrs ? ":dn" : "",
00572                      !BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
00573                      !BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
00574                      vtmp.bv_len ? vtmp.bv_val : "" );
00575               ber_memfree_x( vtmp.bv_val, memctx );
00576               break;
00577 
00578        case SLAPD_FILTER_COMPUTED:
00579               switch ( f->f_result ) {
00580               /* FIXME: treat UNDEFINED as FALSE */
00581               case SLAPD_COMPARE_UNDEFINED:
00582 computed:;
00583                      if ( META_BACK_TGT_NOUNDEFFILTER( dc->target ) ) {
00584                             return LDAP_COMPARE_FALSE;
00585                      }
00586                      /* fallthru */
00587 
00588               case LDAP_COMPARE_FALSE:
00589                      if ( META_BACK_TGT_T_F( dc->target ) ) {
00590                             tmp = &ber_bvtf_false;
00591                             break;
00592                      }
00593                      tmp = &ber_bvfalse;
00594                      break;
00595 
00596               case LDAP_COMPARE_TRUE:
00597                      if ( META_BACK_TGT_T_F( dc->target ) ) {
00598                             tmp = &ber_bvtf_true;
00599                             break;
00600                      }
00601 
00602                      tmp = &ber_bvtrue;
00603                      break;
00604 
00605               default:
00606                      tmp = &ber_bverror;
00607                      break;
00608               }
00609 
00610               ber_dupbv_x( fstr, tmp, memctx );
00611               break;
00612 
00613        default:
00614               ber_dupbv_x( fstr, &ber_bvunknown, memctx );
00615               break;
00616        }
00617 
00618        return 0;
00619 }
00620 
00621 int
00622 ldap_back_filter_map_rewrite(
00623               dncookie             *dc,
00624               Filter               *f,
00625               struct berval *fstr,
00626               int                         remap,
00627               void                 *memctx )
00628 {
00629        int           rc;
00630        dncookie      fdc;
00631        struct berval ftmp;
00632        static char   *dmy = "";
00633 
00634        rc = ldap_back_int_filter_map_rewrite( dc, f, fstr, remap, memctx );
00635 
00636 #ifdef ENABLE_REWRITE
00637        if ( rc != LDAP_SUCCESS ) {
00638               return rc;
00639        }
00640 
00641        fdc = *dc;
00642        ftmp = *fstr;
00643 
00644        fdc.ctx = "searchFilter";
00645        
00646        switch ( rewrite_session( fdc.target->mt_rwmap.rwm_rw, fdc.ctx,
00647                             ( !BER_BVISEMPTY( &ftmp ) ? ftmp.bv_val : dmy ),
00648                             fdc.conn, &fstr->bv_val ) )
00649        {
00650        case REWRITE_REGEXEC_OK:
00651               if ( !BER_BVISNULL( fstr ) ) {
00652                      fstr->bv_len = strlen( fstr->bv_val );
00653 
00654               } else {
00655                      *fstr = ftmp;
00656               }
00657               Debug( LDAP_DEBUG_ARGS,
00658                      "[rw] %s: \"%s\" -> \"%s\"\n",
00659                      fdc.ctx, BER_BVISNULL( &ftmp ) ? "" : ftmp.bv_val,
00660                      BER_BVISNULL( fstr ) ? "" : fstr->bv_val );             
00661               rc = LDAP_SUCCESS;
00662               break;
00663               
00664        case REWRITE_REGEXEC_UNWILLING:
00665               if ( fdc.rs ) {
00666                      fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
00667                      fdc.rs->sr_text = "Operation not allowed";
00668               }
00669               rc = LDAP_UNWILLING_TO_PERFORM;
00670               break;
00671                      
00672        case REWRITE_REGEXEC_ERR:
00673               if ( fdc.rs ) {
00674                      fdc.rs->sr_err = LDAP_OTHER;
00675                      fdc.rs->sr_text = "Rewrite error";
00676               }
00677               rc = LDAP_OTHER;
00678               break;
00679        }
00680 
00681        if ( fstr->bv_val == dmy ) {
00682               BER_BVZERO( fstr );
00683 
00684        } else if ( fstr->bv_val != ftmp.bv_val ) {
00685               /* NOTE: need to realloc mapped filter on slab
00686                * and free the original one, until librewrite
00687                * becomes slab-aware
00688                */
00689               ber_dupbv_x( &ftmp, fstr, memctx );
00690               ch_free( fstr->bv_val );
00691               *fstr = ftmp;
00692        }
00693 #endif /* ENABLE_REWRITE */
00694 
00695        return rc;
00696 }
00697 
00698 int
00699 ldap_back_referral_result_rewrite(
00700        dncookie             *dc,
00701        BerVarray            a_vals,
00702        void                 *memctx
00703 )
00704 {
00705        int           i, last;
00706 
00707        assert( dc != NULL );
00708        assert( a_vals != NULL );
00709 
00710        for ( last = 0; !BER_BVISNULL( &a_vals[ last ] ); last++ )
00711               ;
00712        last--;
00713 
00714        for ( i = 0; !BER_BVISNULL( &a_vals[ i ] ); i++ ) {
00715               struct berval dn,
00716                             olddn = BER_BVNULL;
00717               int           rc;
00718               LDAPURLDesc   *ludp;
00719 
00720               rc = ldap_url_parse( a_vals[ i ].bv_val, &ludp );
00721               if ( rc != LDAP_URL_SUCCESS ) {
00722                      /* leave attr untouched if massage failed */
00723                      continue;
00724               }
00725 
00726               /* FIXME: URLs like "ldap:///dc=suffix" if passed
00727                * thru ldap_url_parse() and ldap_url_desc2str()
00728                * get rewritten as "ldap:///dc=suffix??base";
00729                * we don't want this to occur... */
00730               if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
00731                      ludp->lud_scope = LDAP_SCOPE_DEFAULT;
00732               }
00733 
00734               ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
00735               
00736               rc = ldap_back_dn_massage( dc, &olddn, &dn );
00737               switch ( rc ) {
00738               case LDAP_UNWILLING_TO_PERFORM:
00739                      /*
00740                       * FIXME: need to check if it may be considered 
00741                       * legal to trim values when adding/modifying;
00742                       * it should be when searching (e.g. ACLs).
00743                       */
00744                      ber_memfree( a_vals[ i ].bv_val );
00745                      if ( last > i ) {
00746                             a_vals[ i ] = a_vals[ last ];
00747                      }
00748                      BER_BVZERO( &a_vals[ last ] );
00749                      last--;
00750                      i--;
00751                      break;
00752 
00753               default:
00754                      /* leave attr untouched if massage failed */
00755                      if ( !BER_BVISNULL( &dn ) && olddn.bv_val != dn.bv_val )
00756                      {
00757                             char   *newurl;
00758 
00759                             ludp->lud_dn = dn.bv_val;
00760                             newurl = ldap_url_desc2str( ludp );
00761                             free( dn.bv_val );
00762                             if ( newurl == NULL ) {
00763                                    /* FIXME: leave attr untouched
00764                                     * even if ldap_url_desc2str failed...
00765                                     */
00766                                    break;
00767                             }
00768 
00769                             ber_memfree_x( a_vals[ i ].bv_val, memctx );
00770                             ber_str2bv_x( newurl, 0, 1, &a_vals[ i ], memctx );
00771                             ber_memfree( newurl );
00772                             ludp->lud_dn = olddn.bv_val;
00773                      }
00774                      break;
00775               }
00776 
00777               ldap_free_urldesc( ludp );
00778        }
00779 
00780        return 0;
00781 }
00782 
00783 /*
00784  * I don't like this much, but we need two different
00785  * functions because different heap managers may be
00786  * in use in back-ldap/meta to reduce the amount of
00787  * calls to malloc routines, and some of the free()
00788  * routines may be macros with args
00789  */
00790 int
00791 ldap_dnattr_rewrite(
00792        dncookie             *dc,
00793        BerVarray            a_vals
00794 )
00795 {
00796        struct berval bv;
00797        int           i, last;
00798 
00799        assert( a_vals != NULL );
00800 
00801        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
00802               ;
00803        last--;
00804 
00805        for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
00806               switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
00807               case LDAP_UNWILLING_TO_PERFORM:
00808                      /*
00809                       * FIXME: need to check if it may be considered 
00810                       * legal to trim values when adding/modifying;
00811                       * it should be when searching (e.g. ACLs).
00812                       */
00813                      ch_free( a_vals[i].bv_val );
00814                      if ( last > i ) {
00815                             a_vals[i] = a_vals[last];
00816                      }
00817                      BER_BVZERO( &a_vals[last] );
00818                      last--;
00819                      break;
00820 
00821               default:
00822                      /* leave attr untouched if massage failed */
00823                      if ( !BER_BVISNULL( &bv ) && bv.bv_val != a_vals[i].bv_val ) {
00824                             ch_free( a_vals[i].bv_val );
00825                             a_vals[i] = bv;
00826                      }
00827                      break;
00828               }
00829        }
00830        
00831        return 0;
00832 }
00833 
00834 int
00835 ldap_dnattr_result_rewrite(
00836        dncookie             *dc,
00837        BerVarray            a_vals
00838 )
00839 {
00840        struct berval bv;
00841        int           i, last;
00842 
00843        assert( a_vals != NULL );
00844 
00845        for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
00846               ;
00847        last--;
00848 
00849        for ( i = 0; !BER_BVISNULL( &a_vals[i] ); i++ ) {
00850               switch ( ldap_back_dn_massage( dc, &a_vals[i], &bv ) ) {
00851               case LDAP_UNWILLING_TO_PERFORM:
00852                      /*
00853                       * FIXME: need to check if it may be considered 
00854                       * legal to trim values when adding/modifying;
00855                       * it should be when searching (e.g. ACLs).
00856                       */
00857                      ber_memfree( a_vals[i].bv_val );
00858                      if ( last > i ) {
00859                             a_vals[i] = a_vals[last];
00860                      }
00861                      BER_BVZERO( &a_vals[last] );
00862                      last--;
00863                      break;
00864 
00865               default:
00866                      /* leave attr untouched if massage failed */
00867                      if ( !BER_BVISNULL( &bv ) && a_vals[i].bv_val != bv.bv_val ) {
00868                             ber_memfree( a_vals[i].bv_val );
00869                             a_vals[i] = bv;
00870                      }
00871                      break;
00872               }
00873        }
00874 
00875        return 0;
00876 }
00877