Newer
Older
/* rwmmap.c - rewrite/mapping routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Portions Copyright 1999-2003 Howard Chu.
* Portions Copyright 2000-2003 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by the Howard Chu for inclusion
* in OpenLDAP Software and subsequently enhanced by Pierangelo
* Masarati.
*/
#include "portable.h"
Pierangelo Masarati
committed
#ifdef SLAPD_OVER_RWM
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "slap.h"
#include "rwm.h"
#undef ldap_debug /* silence a warning in ldap-int.h */
#include "../../../libraries/libldap/ldap-int.h"
int
Pierangelo Masarati
committed
rwm_mapping_cmp( const void *c1, const void *c2 )
{
struct ldapmapping *map1 = (struct ldapmapping *)c1;
struct ldapmapping *map2 = (struct ldapmapping *)c2;
Pierangelo Masarati
committed
int rc = map1->m_src.bv_len - map2->m_src.bv_len;
Pierangelo Masarati
committed
if ( rc ) {
return rc;
}
Pierangelo Masarati
committed
return strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val );
Pierangelo Masarati
committed
rwm_mapping_dup( void *c1, void *c2 )
{
struct ldapmapping *map1 = (struct ldapmapping *)c1;
struct ldapmapping *map2 = (struct ldapmapping *)c2;
Pierangelo Masarati
committed
int rc = map1->m_src.bv_len - map2->m_src.bv_len;
if ( rc ) {
return 0;
}
Pierangelo Masarati
committed
return ( ( strcasecmp( map1->m_src.bv_val, map2->m_src.bv_val ) == 0 ) ? -1 : 0 );
Pierangelo Masarati
committed
rwm_map_init( struct ldapmap *lm, struct ldapmapping **m )
struct ldapmapping *mapping;
const char *text;
int rc;
Hallvard Furuseth
committed
assert( m != NULL );
*m = NULL;
mapping = (struct ldapmapping *)ch_calloc( 2,
sizeof( struct ldapmapping ) );
if ( mapping == NULL ) {
/* FIXME: I don't think this is needed any more... */
rc = slap_str2ad( "objectClass", &mapping[0].m_src_ad, &text );
mapping[0].m_dst_ad = mapping[0].m_src_ad;
ber_dupbv( &mapping[0].m_src, &mapping[0].m_src_ad->ad_cname );
ber_dupbv( &mapping[0].m_dst, &mapping[0].m_src );
mapping[1].m_src = mapping[0].m_src;
mapping[1].m_dst = mapping[0].m_dst;
mapping[1].m_src_ad = mapping[0].m_src_ad;
mapping[1].m_dst_ad = mapping[1].m_src_ad;
avl_insert( &lm->map, (caddr_t)&mapping[0],
Pierangelo Masarati
committed
rwm_mapping_cmp, rwm_mapping_dup );
avl_insert( &lm->remap, (caddr_t)&mapping[1],
Pierangelo Masarati
committed
rwm_mapping_cmp, rwm_mapping_dup );
int
rwm_mapping( struct ldapmap *map, struct berval *s, struct ldapmapping **m, int remap )
Hallvard Furuseth
committed
assert( m != NULL );
Pierangelo Masarati
committed
} else {
Pierangelo Masarati
committed
}
Pierangelo Masarati
committed
fmapping.m_src = *s;
*m = (struct ldapmapping *)avl_find( tree, (caddr_t)&fmapping,
Pierangelo Masarati
committed
rwm_mapping_cmp );
if ( *m == NULL ) {
return map->drop_missing;
}
return 0;
}
void
rwm_map( struct ldapmap *map, struct berval *s, struct berval *bv, int remap )
{
struct ldapmapping *mapping;
BER_BVZERO( bv );
( void )rwm_mapping( map, s, &mapping, remap );
Pierangelo Masarati
committed
if ( mapping != NULL ) {
Pierangelo Masarati
committed
*bv = mapping->m_dst;
}
Pierangelo Masarati
committed
if ( !map->drop_missing ) {
Pierangelo Masarati
committed
}
}
/*
* Map attribute names in place
*/
int
rwm_map_attrnames(
struct ldapmap *at_map,
struct ldapmap *oc_map,
AttributeName *an,
AttributeName **anp,
int remap
)
{
int i, j;
Hallvard Furuseth
committed
assert( anp != NULL );
Pierangelo Masarati
committed
*anp = NULL;
if ( an == NULL ) {
return LDAP_SUCCESS;
}
for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ )
/* just count */ ;
*anp = ch_malloc( ( i + 1 )* sizeof( AttributeName ) );
if ( *anp == NULL ) {
return LDAP_NO_MEMORY;
}
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
for ( i = 0, j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
struct ldapmapping *m;
int at_drop_missing = 0,
oc_drop_missing = 0;
if ( an[i].an_desc ) {
if ( !at_map ) {
/* FIXME: better leave as is? */
continue;
}
at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
if ( at_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
continue;
}
if ( !m ) {
(*anp)[j] = an[i];
j++;
continue;
}
(*anp)[j] = an[i];
if ( remap == RWM_MAP ) {
(*anp)[j].an_name = m->m_dst;
(*anp)[j].an_desc = m->m_dst_ad;
} else {
(*anp)[j].an_name = m->m_src;
(*anp)[j].an_desc = m->m_src_ad;
}
j++;
continue;
} else if ( an[i].an_oc ) {
if ( !oc_map ) {
/* FIXME: better leave as is? */
continue;
}
oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
if ( oc_drop_missing || ( m && BER_BVISNULL( &m->m_dst ) ) ) {
continue;
}
if ( !m ) {
(*anp)[j] = an[i];
j++;
continue;
}
(*anp)[j] = an[i];
if ( remap == RWM_MAP ) {
(*anp)[j].an_name = m->m_dst;
(*anp)[j].an_oc = m->m_dst_oc;
} else {
(*anp)[j].an_name = m->m_src;
(*anp)[j].an_oc = m->m_src_oc;
}
} else {
at_drop_missing = rwm_mapping( at_map, &an[i].an_name, &m, remap );
if ( at_drop_missing || !m ) {
oc_drop_missing = rwm_mapping( oc_map, &an[i].an_name, &m, remap );
/* if both at_map and oc_map required to drop missing,
* then do it */
if ( oc_drop_missing && at_drop_missing ) {
continue;
}
/* if no oc_map mapping was found and at_map required
* to drop missing, then do it; otherwise, at_map wins
* and an is considered an attr and is left unchanged */
if ( !m ) {
if ( at_drop_missing ) {
continue;
}
(*anp)[j] = an[i];
j++;
continue;
}
if ( BER_BVISNULL( &m->m_dst ) ) {
continue;
}
(*anp)[j] = an[i];
if ( remap == RWM_MAP ) {
(*anp)[j].an_name = m->m_dst;
(*anp)[j].an_oc = m->m_dst_oc;
} else {
(*anp)[j].an_name = m->m_src;
(*anp)[j].an_oc = m->m_src_oc;
}
j++;
continue;
}
if ( !BER_BVISNULL( &m->m_dst ) ) {
(*anp)[j] = an[i];
if ( remap == RWM_MAP ) {
(*anp)[j].an_name = m->m_dst;
(*anp)[j].an_desc = m->m_dst_ad;
} else {
(*anp)[j].an_name = m->m_src;
(*anp)[j].an_desc = m->m_src_ad;
}
j++;
continue;
}
}
}
if ( j == 0 && i != 0 ) {
memset( &(*anp)[0], 0, sizeof( AttributeName ) );
BER_BVSTR( &(*anp)[0].an_name, LDAP_NO_ATTRS );
}
memset( &(*anp)[j], 0, sizeof( AttributeName ) );
}
int
rwm_map_attrs(
struct ldapmap *at_map,
AttributeName *an,
int remap,
char ***mapped_attrs
)
{
int i, j;
char **na;
Pierangelo Masarati
committed
if ( an == NULL ) {
*mapped_attrs = NULL;
return LDAP_SUCCESS;
}
for ( i = 0; !BER_BVISNULL( &an[ i ].an_name ); i++ ) {
Pierangelo Masarati
committed
na = (char **)ch_calloc( i + 1, sizeof( char * ) );
*mapped_attrs = NULL;
return LDAP_NO_MEMORY;
}
for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) {
struct ldapmapping *mapping;
if ( rwm_mapping( at_map, &an[i].an_name, &mapping, remap ) ) {
if ( !mapping ) {
na[ j++ ] = an[ i ].an_name.bv_val;
} else if ( !BER_BVISNULL( &mapping->m_dst ) ) {
na[ j++ ] = mapping->m_dst.bv_val;
Pierangelo Masarati
committed
}
Pierangelo Masarati
committed
if ( j == 0 && i != 0 ) {
na[ j++ ] = LDAP_NO_ATTRS;
Pierangelo Masarati
committed
}
*mapped_attrs = na;
return LDAP_SUCCESS;
}
Pierangelo Masarati
committed
static int
map_attr_value(
dncookie *dc,
AttributeDescription **adp,
struct berval *mapped_attr,
struct berval *value,
struct berval *mapped_value,
int remap )
{
Pierangelo Masarati
committed
struct berval vtmp = BER_BVNULL;
AttributeDescription *ad = *adp;
struct ldapmapping *mapping = NULL;
rwm_mapping( &dc->rwmap->rwm_at, &ad->ad_cname, &mapping, remap );
if ( mapping == NULL ) {
if ( dc->rwmap->rwm_at.drop_missing ) {
return -1;
*mapped_attr = ad->ad_cname;
} else {
*mapped_attr = mapping->m_dst;
if ( value != NULL ) {
assert( mapped_value != NULL );
Pierangelo Masarati
committed
if ( ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
{
dncookie fdc = *dc;
int rc;
#ifdef ENABLE_REWRITE
fdc.ctx = "searchFilterAttrDN";
#endif /* ENABLE_REWRITE */
vtmp = *value;
rc = rwm_dn_massage_normalize( &fdc, value, &vtmp );
switch ( rc ) {
case LDAP_SUCCESS:
if ( vtmp.bv_val != value->bv_val ) {
freeval = 1;
}
break;
case LDAP_UNWILLING_TO_PERFORM:
case LDAP_OTHER:
default:
return -1;
}
} else if ( ad == slap_schema.si_ad_objectClass
|| ad == slap_schema.si_ad_structuralObjectClass )
{
rwm_map( &dc->rwmap->rwm_oc, value, &vtmp, remap );
if ( BER_BVISNULL( &vtmp ) || BER_BVISEMPTY( &vtmp ) ) {
vtmp = *value;
}
} else {
vtmp = *value;
}
filter_escape_value( &vtmp, mapped_value );
if ( freeval ) {
ch_free( vtmp.bv_val );
}
if ( mapping != NULL ) {
assert( mapping->m_dst_ad != NULL );
*adp = mapping->m_dst_ad;
}
Pierangelo Masarati
committed
static int
rwm_int_filter_map_rewrite(
dncookie *dc,
Filter *f,
{
int i;
Filter *p;
Pierangelo Masarati
committed
struct berval atmp,
vtmp,
tmp;
static struct berval
/* better than nothing... */
ber_bvfalse = BER_BVC( "(!(objectClass=*))" ),
ber_bvtf_false = BER_BVC( "(|)" ),
/* better than nothing... */
ber_bvtrue = BER_BVC( "(objectClass=*)" ),
ber_bvtf_true = BER_BVC( "(&)" ),
#if 0
/* no longer needed; preserved for completeness */
Pierangelo Masarati
committed
ber_bvundefined = BER_BVC( "(?=undefined)" ),
Pierangelo Masarati
committed
ber_bverror = BER_BVC( "(?=error)" ),
ber_bvunknown = BER_BVC( "(?=unknown)" ),
ber_bvnone = BER_BVC( "(?=none)" );
ber_len_t len;
if ( f == NULL ) {
Pierangelo Masarati
committed
ber_dupbv( fstr, &ber_bvnone );
return -1;
}
switch ( f->f_choice ) {
case LDAP_FILTER_EQUALITY:
if ( map_attr_value( dc, &f->f_av_desc, &atmp,
{
return -1;
}
fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(=)" );
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
atmp.bv_val, vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
break;
case LDAP_FILTER_GE:
if ( map_attr_value( dc, &f->f_av_desc, &atmp,
{
return -1;
}
fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(>=)" );
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
atmp.bv_val, vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
break;
case LDAP_FILTER_LE:
if ( map_attr_value( dc, &f->f_av_desc, &atmp,
{
return -1;
}
fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(<=)" );
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
atmp.bv_val, vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
break;
case LDAP_FILTER_APPROX:
if ( map_attr_value( dc, &f->f_av_desc, &atmp,
{
return -1;
}
fstr->bv_len = atmp.bv_len + vtmp.bv_len + STRLENOF( "(~=)" );
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
atmp.bv_val, vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
break;
case LDAP_FILTER_SUBSTRINGS:
if ( map_attr_value( dc, &f->f_sub_desc, &atmp,
{
return -1;
}
/* cannot be a DN ... */
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
atmp.bv_val );
len = fstr->bv_len;
filter_escape_value( &f->f_sub_initial, &vtmp );
fstr->bv_len += vtmp.bv_len;
fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
snprintf( &fstr->bv_val[len - 2], vtmp.bv_len + 3,
/* "(attr=" */ "%s*)",
vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
}
if ( f->f_sub_any != NULL ) {
for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
len = fstr->bv_len;
filter_escape_value( &f->f_sub_any[i], &vtmp );
fstr->bv_len += vtmp.bv_len + 1;
fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
/* "(attr=[init]*[any*]" */ "%s*)",
vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
len = fstr->bv_len;
filter_escape_value( &f->f_sub_final, &vtmp );
fstr->bv_len += vtmp.bv_len;
fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
snprintf( &fstr->bv_val[len - 1], vtmp.bv_len + 3,
/* "(attr=[init*][any*]" */ "%s)",
vtmp.bv_val );
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
}
break;
case LDAP_FILTER_PRESENT:
if ( map_attr_value( dc, &f->f_desc, &atmp,
{
return -1;
}
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
atmp.bv_val );
break;
case LDAP_FILTER_AND:
case LDAP_FILTER_OR:
case LDAP_FILTER_NOT:
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
f->f_choice == LDAP_FILTER_AND ? '&' :
f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
for ( p = f->f_list; p != NULL; p = p->f_next ) {
len = fstr->bv_len;
{
return -1;
}
fstr->bv_len += vtmp.bv_len;
fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
snprintf( &fstr->bv_val[len-1], vtmp.bv_len + 2,
/*"("*/ "%s)", vtmp.bv_val );
ch_free( vtmp.bv_val );
}
break;
case LDAP_FILTER_EXT: {
if ( f->f_mr_desc ) {
if ( map_attr_value( dc, &f->f_mr_desc, &atmp,
{
return -1;
}
} else {
filter_escape_value( &f->f_mr_value, &vtmp );
}
fstr->bv_len = atmp.bv_len +
Pierangelo Masarati
committed
( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len + 1 : 0 ) +
Pierangelo Masarati
committed
fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
atmp.bv_val,
f->f_mr_dnattrs ? ":dn" : "",
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? ":" : "",
!BER_BVISEMPTY( &f->f_mr_rule_text ) ? f->f_mr_rule_text.bv_val : "",
Pierangelo Masarati
committed
ch_free( vtmp.bv_val );
break;
}
case SLAPD_FILTER_COMPUTED:
Pierangelo Masarati
committed
switch ( f->f_result ) {
case LDAP_COMPARE_FALSE:
if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
tmp = ber_bvtf_false;
/* fallthru */
case SLAPD_COMPARE_UNDEFINED:
tmp = ber_bvfalse;
Pierangelo Masarati
committed
break;
Pierangelo Masarati
committed
case LDAP_COMPARE_TRUE:
if ( dc->rwmap->rwm_flags & RWM_F_SUPPORT_T_F ) {
tmp = ber_bvtf_true;
} else {
tmp = ber_bvtrue;
}
Pierangelo Masarati
committed
break;
default:
tmp = ber_bverror;
break;
}
ber_dupbv( fstr, &tmp );
break;
Pierangelo Masarati
committed
ber_dupbv( fstr, &ber_bvunknown );
break;
}
return 0;
}
Pierangelo Masarati
committed
int
rwm_filter_map_rewrite(
dncookie *dc,
Filter *f,
Pierangelo Masarati
committed
{
int rc;
dncookie fdc;
struct berval ftmp;
Pierangelo Masarati
committed
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
}
fdc = *dc;
ftmp = *fstr;
fdc.ctx = "searchFilter";
switch ( rewrite_session( fdc.rwmap->rwm_rw, fdc.ctx,
fdc.conn, &fstr->bv_val ) )
{
Pierangelo Masarati
committed
case REWRITE_REGEXEC_OK:
Pierangelo Masarati
committed
fstr->bv_len = strlen( fstr->bv_val );
Pierangelo Masarati
committed
ch_free( ftmp.bv_val );
Pierangelo Masarati
committed
} else {
*fstr = ftmp;
}
Debug( LDAP_DEBUG_ARGS,
"[rw] %s: \"%s\" -> \"%s\"\n",
fdc.ctx, ftmp.bv_val, fstr->bv_val );
Pierangelo Masarati
committed
rc = LDAP_SUCCESS;
break;
case REWRITE_REGEXEC_UNWILLING:
if ( fdc.rs ) {
fdc.rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
fdc.rs->sr_text = "Operation not allowed";
}
rc = LDAP_UNWILLING_TO_PERFORM;
break;
case REWRITE_REGEXEC_ERR:
if ( fdc.rs ) {
fdc.rs->sr_err = LDAP_OTHER;
fdc.rs->sr_text = "Rewrite error";
}
rc = LDAP_OTHER;
break;
}
#endif /* ENABLE_REWRITE */
return rc;
}
/*
* I don't like this much, but we need two different
* functions because different heap managers may be
* in use in back-ldap/meta to reduce the amount of
* calls to malloc routines, and some of the free()
* routines may be macros with args
*/
int
Pierangelo Masarati
committed
rwm_referral_rewrite(
Pierangelo Masarati
committed
Operation *op,
SlapReply *rs,
void *cookie,
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
int i, last;
dncookie dc;
Pierangelo Masarati
committed
struct berval dn = BER_BVNULL,
ndn = BER_BVNULL;
Hallvard Furuseth
committed
assert( a_vals != NULL );
Pierangelo Masarati
committed
/*
Pierangelo Masarati
committed
* Rewrite the dn if needed
Pierangelo Masarati
committed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = (char *)cookie;
#else /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
dc.tofrom = ((int *)cookie)[0];
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
for ( last = 0; !BER_BVISNULL( &a_vals[last] ); last++ )
;
last--;
if ( pa_nvals != NULL ) {
if ( *pa_nvals == NULL ) {
Pierangelo Masarati
committed
*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
struct berval olddn = BER_BVNULL,
oldval;
Pierangelo Masarati
committed
LDAPURLDesc *ludp;
oldval = a_vals[i];
rc = ldap_url_parse( oldval.bv_val, &ludp );
if ( rc != LDAP_URL_SUCCESS ) {
/* leave attr untouched if massage failed */
if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
ber_dupbv( &(*pa_nvals)[i], &oldval );
}
continue;
}
Pierangelo Masarati
committed
/* FIXME: URLs like "ldap:///dc=suffix" if passed
* thru ldap_url_parse() and ldap_url_desc2str()
* get rewritten as "ldap:///dc=suffix??base";
* we don't want this to occur... */
if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
ludp->lud_scope = LDAP_SCOPE_DEFAULT;
}
Pierangelo Masarati
committed
ber_str2bv( ludp->lud_dn, 0, 0, &olddn );
Pierangelo Masarati
committed
dn = olddn;
if ( pa_nvals ) {
ndn = olddn;
rc = rwm_dn_massage_pretty_normalize( &dc, &olddn,
&dn, &ndn );
} else {
rc = rwm_dn_massage_pretty( &dc, &olddn, &dn );
}
case LDAP_UNWILLING_TO_PERFORM:
/*
* FIXME: need to check if it may be considered
* legal to trim values when adding/modifying;
* it should be when searching (e.g. ACLs).
*/
ch_free( a_vals[i].bv_val );
if (last > i ) {
a_vals[i] = a_vals[last];
if ( pa_nvals ) {
(*pa_nvals)[i] = (*pa_nvals)[last];
}
}
BER_BVZERO( &a_vals[last] );
if ( pa_nvals ) {
BER_BVZERO( &(*pa_nvals)[last] );
}
last--;
break;
Pierangelo Masarati
committed
if ( !BER_BVISNULL( &dn ) && dn.bv_val != olddn.bv_val ) {
char *newurl;
ludp->lud_dn = dn.bv_val;
newurl = ldap_url_desc2str( ludp );
Pierangelo Masarati
committed
ludp->lud_dn = olddn.bv_val;
ch_free( dn.bv_val );
Pierangelo Masarati
committed
if ( newurl == NULL ) {
/* FIXME: leave attr untouched
Pierangelo Masarati
committed
* even if ldap_url_desc2str failed...
*/
Pierangelo Masarati
committed
break;
}
ber_str2bv( newurl, 0, 1, &a_vals[i] );
LDAP_FREE( newurl );
Pierangelo Masarati
committed
ludp->lud_dn = ndn.bv_val;
newurl = ldap_url_desc2str( ludp );
Pierangelo Masarati
committed
ludp->lud_dn = olddn.bv_val;
ch_free( ndn.bv_val );
Pierangelo Masarati
committed
if ( newurl == NULL ) {
/* FIXME: leave attr untouched
Pierangelo Masarati
committed
* even if ldap_url_desc2str failed...
*/
Pierangelo Masarati
committed
ch_free( a_vals[i].bv_val );
a_vals[i] = oldval;
break;
}
if ( !BER_BVISNULL( &(*pa_nvals)[i] ) ) {
ch_free( (*pa_nvals)[i].bv_val );
}
Pierangelo Masarati
committed
ber_str2bv( newurl, 0, 1, &(*pa_nvals)[i] );
LDAP_FREE( newurl );
Pierangelo Masarati
committed
ch_free( oldval.bv_val );
ludp->lud_dn = olddn.bv_val;
default:
/* leave attr untouched if massage failed */
if ( pa_nvals && BER_BVISNULL( &(*pa_nvals)[i] ) ) {
Pierangelo Masarati
committed
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
ber_dupbv( &(*pa_nvals)[i], &a_vals[i] );
}
break;
}
ldap_free_urldesc( ludp );
}
return 0;
}
/*
* I don't like this much, but we need two different
* functions because different heap managers may be
* in use in back-ldap/meta to reduce the amount of
* calls to malloc routines, and some of the free()
* routines may be macros with args
*/
int
rwm_dnattr_rewrite(
Operation *op,
SlapReply *rs,
void *cookie,
BerVarray a_vals,
BerVarray *pa_nvals )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
int i, last;
dncookie dc;
Pierangelo Masarati
committed
struct berval dn = BER_BVNULL,
ndn = BER_BVNULL;
Pierangelo Masarati
committed
BerVarray in;
if ( a_vals ) {
in = a_vals;
} else {
if ( pa_nvals == NULL || *pa_nvals == NULL ) {
return LDAP_OTHER;
}
in = *pa_nvals;
}
/*
* Rewrite the dn if needed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = (char *)cookie;
#else /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
dc.tofrom = ((int *)cookie)[0];
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
for ( last = 0; !BER_BVISNULL( &in[last] ); last++ );
Pierangelo Masarati
committed
last--;
Pierangelo Masarati
committed
if ( pa_nvals != NULL ) {
if ( *pa_nvals == NULL ) {
Pierangelo Masarati
committed
*pa_nvals = ch_malloc( ( last + 2 ) * sizeof(struct berval) );
memset( *pa_nvals, 0, ( last + 2 ) * sizeof(struct berval) );
Pierangelo Masarati
committed
}
}
for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
int rc;
Pierangelo Masarati
committed
if ( a_vals ) {
dn = in[i];