Newer
Older
/* rwm.c - rewrite/remap operations */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Portions Copyright 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>.
*/
#include "portable.h"
Pierangelo Masarati
committed
#ifdef SLAPD_OVER_RWM
#include <ac/string.h>
#include "slap.h"
#include "rwm.h"
static int
rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
int rc = 0;
dncookie dc;
/*
Pierangelo Masarati
committed
* 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 */
dc.tofrom = ((int *)cookie)[0];
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
/* NOTE: in those cases where only the ndn is available,
* and the caller sets op->o_req_dn = op->o_req_ndn,
* only rewrite the op->o_req_ndn and use it as
* op->o_req_dn as well */
if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
dnp = &dn;
}
rc = rwm_dn_massage( &dc, &op->o_req_dn, dnp, &ndn );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( ( dnp && dn.bv_val == op->o_req_dn.bv_val ) ||
( !dnp && ndn.bv_val == op->o_req_ndn.bv_val ) ) {
op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
if ( dnp ) {
op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
op->o_req_dn = dn;
} else {
op->o_req_dn = ndn;
}
Pierangelo Masarati
committed
op->o_req_ndn = ndn;
return LDAP_SUCCESS;
}
static int
Pierangelo Masarati
committed
rwm_op_add( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
int rc,
Pierangelo Masarati
committed
Attribute **ap = NULL;
char *olddn = op->o_req_dn.bv_val;
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "addDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "addDN massage error" );
Pierangelo Masarati
committed
return -1;
}
if ( olddn != op->o_req_dn.bv_val ) {
Pierangelo Masarati
committed
ch_free( op->ora_e->e_name.bv_val );
ch_free( op->ora_e->e_nname.bv_val );
ber_dupbv( &op->ora_e->e_name, &op->o_req_dn );
ber_dupbv( &op->ora_e->e_nname, &op->o_req_ndn );
}
Pierangelo Masarati
committed
/* Count number of attributes in entry */
for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
struct berval mapped;
Attribute *a;
if ( (*ap)->a_desc->ad_type->sat_no_user_mod ) {
goto next_attr;
Pierangelo Masarati
committed
}
rwm_map( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
&mapped, RWM_MAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
Pierangelo Masarati
committed
goto cleanup_attr;
}
if ( (*ap)->a_desc->ad_type->sat_syntax
== slap_schema.si_syn_distinguishedName )
{
/*
* FIXME: rewrite could fail; in this case
* the operation should give up, right?
*/
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
(*ap)->a_vals,
(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
#else /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
rc = 1;
rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals,
(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
if ( rc ) {
goto cleanup_attr;
}
Pierangelo Masarati
committed
} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
#ifdef ENABLE_REWRITE
rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
Pierangelo Masarati
committed
(*ap)->a_vals,
(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
#else /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
rc = 1;
rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals,
(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
if ( rc != LDAP_SUCCESS ) {
goto cleanup_attr;
}
Pierangelo Masarati
committed
}
Pierangelo Masarati
committed
next_attr:;
Pierangelo Masarati
committed
ap = &(*ap)->a_next;
continue;
cleanup_attr:;
/* FIXME: leaking attribute/values? */
a = *ap;
*ap = (*ap)->a_next;
Pierangelo Masarati
committed
/* TODO: map attribute types, values of DN-valued attributes ... */
return SLAP_CB_CONTINUE;
}
static int
Pierangelo Masarati
committed
rwm_op_bind( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
Pierangelo Masarati
committed
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
Pierangelo Masarati
committed
int rc;
#ifdef ENABLE_REWRITE
( void )rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
Pierangelo Masarati
committed
( void )rewrite_session_init( rwmap->rwm_rw, op->o_conn );
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "bindDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "bindDN massage error" );
Pierangelo Masarati
committed
return -1;
}
return SLAP_CB_CONTINUE;
}
Pierangelo Masarati
committed
static int
Pierangelo Masarati
committed
rwm_op_unbind( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
#ifdef ENABLE_REWRITE
rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
#endif /* ENABLE_REWRITE */
Pierangelo Masarati
committed
return SLAP_CB_CONTINUE;
}
Pierangelo Masarati
committed
rwm_op_compare( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
int rc;
struct berval mapped_at = BER_BVNULL,
mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "compareDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "compareDN massage error" );
Pierangelo Masarati
committed
return -1;
}
/* if the attribute is an objectClass, try to remap its value */
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
|| op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
{
rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
&mapped_vals[0], RWM_MAP );
if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
Pierangelo Masarati
committed
{
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
return -1;
} else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
free( op->orc_ava->aa_value.bv_val );
op->orc_ava->aa_value = mapped_vals[0];
}
mapped_at = op->orc_ava->aa_desc->ad_cname;
} else {
struct ldapmapping *mapping = NULL;
AttributeDescription *ad = op->orc_ava->aa_desc;
( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
&mapping, RWM_MAP );
if ( mapping == NULL ) {
if ( rwmap->rwm_at.drop_missing ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
return -1;
}
} else {
ad = mapping->m_dst_ad;
Pierangelo Masarati
committed
}
Pierangelo Masarati
committed
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
{
Pierangelo Masarati
committed
struct berval *mapped_valsp[2];
mapped_valsp[0] = &mapped_vals[0];
mapped_valsp[1] = &mapped_vals[1];
Pierangelo Masarati
committed
mapped_vals[0] = op->orc_ava->aa_value;
Pierangelo Masarati
committed
rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
#else /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
return -1;
}
Pierangelo Masarati
committed
op->orc_ava->aa_value = mapped_vals[0];
Pierangelo Masarati
committed
}
op->orc_ava->aa_desc = ad;
}
return SLAP_CB_CONTINUE;
}
static int
Pierangelo Masarati
committed
rwm_op_delete( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
int rc;
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "deleteDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "deleteDN massage error" );
return -1;
}
return SLAP_CB_CONTINUE;
}
static int
Pierangelo Masarati
committed
rwm_op_modify( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
Modifications **mlp;
Pierangelo Masarati
committed
int rc;
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "modifyDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "modifyDN massage error" );
return -1;
for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
int is_oc = 0;
Modifications *ml;
if ( (*mlp)->sml_desc->ad_type->sat_no_user_mod ) {
goto next_mod;
}
if ( (*mlp)->sml_desc == slap_schema.si_ad_objectClass
|| (*mlp)->sml_desc == slap_schema.si_ad_structuralObjectClass ) {
is_oc = 1;
} else {
struct ldapmapping *m;
int drop_missing;
drop_missing = rwm_mapping( &rwmap->rwm_at, &(*mlp)->sml_desc->ad_cname, &m, RWM_MAP );
if ( drop_missing || ( m != NULL && BER_BVISNULL( &m->m_dst ) ) )
{
goto cleanup_mod;
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
}
if ( m ) {
/* use new attribute description */
assert( m->m_dst_ad );
(*mlp)->sml_desc = m->m_dst_ad;
}
}
if ( (*mlp)->sml_values != NULL ) {
if ( is_oc ) {
int last, j;
for ( last = 0; !BER_BVISNULL( &(*mlp)->sml_values[last] ); last++ )
/* count values */ ;
last--;
for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[j] ); j++ ) {
struct berval mapped = BER_BVNULL;
rwm_map( &rwmap->rwm_oc,
&(*mlp)->sml_values[j],
&mapped, RWM_MAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
/* FIXME: we allow to remove objectClasses as well;
* if the resulting entry is inconsistent, that's
* the relayed database's business...
*/
#if 0
goto cleanup_mod;
#endif
if ( last > j ) {
(*mlp)->sml_values[j] = (*mlp)->sml_values[last];
BER_BVZERO( &(*mlp)->sml_values[last] );
}
last--;
} else {
ch_free( (*mlp)->sml_values[j].bv_val );
ber_dupbv( &(*mlp)->sml_values[j], &mapped );
}
}
} else {
if ( (*mlp)->sml_desc->ad_type->sat_syntax ==
slap_schema.si_syn_distinguishedName )
{
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
(*mlp)->sml_values,
(*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
#else /* ! ENABLE_REWRITE */
(*mlp)->sml_values,
(*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
} else if ( (*mlp)->sml_desc == slap_schema.si_ad_ref ) {
#ifdef ENABLE_REWRITE
rc = rwm_referral_rewrite( op, rs,
"referralAttrDN",
Pierangelo Masarati
committed
(*mlp)->sml_values,
(*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
#else /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
rc = 1;
rc = rwm_referral_rewrite( op, rs, &rc,
(*mlp)->sml_values,
(*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
#endif /* ! ENABLE_REWRITE */
Pierangelo Masarati
committed
if ( rc != LDAP_SUCCESS ) {
goto cleanup_mod;
}
goto cleanup_mod;
continue;
cleanup_mod:;
ml = *mlp;
*mlp = (*mlp)->sml_next;
slap_mod_free( &ml->sml_mod, 0 );
free( ml );
/* TODO: rewrite attribute types, values of DN-valued attributes ... */
return SLAP_CB_CONTINUE;
}
static int
Pierangelo Masarati
committed
rwm_op_modrdn( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
Pierangelo Masarati
committed
int rc;
if ( op->orr_newSup ) {
dncookie dc;
struct berval nnewSup = BER_BVNULL;
struct berval newSup = BER_BVNULL;
/*
* Rewrite the new superior, if defined and required
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "newSuperiorDN";
#else /* ! ENABLE_REWRITE */
dc.tofrom = 0;
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
rc = rwm_dn_massage( &dc, op->orr_newSup, &newSup, &nnewSup );
if ( rc != LDAP_SUCCESS ) {
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
return -1;
}
if ( op->orr_newSup->bv_val != newSup.bv_val ) {
op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx );
op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx );
*op->orr_newSup = newSup;
*op->orr_nnewSup = nnewSup;
}
}
Pierangelo Masarati
committed
/*
* Rewrite the dn, if needed
*/
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "renameDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "renameDN massage error" );
return -1;
Pierangelo Masarati
committed
/* TODO: rewrite newRDN, attribute types,
* values of DN-valued attributes ... */
return SLAP_CB_CONTINUE;
}
static int
rwm_swap_attrs( Operation *op, SlapReply *rs )
{
slap_callback *cb = op->o_callback;
AttributeName *an = (AttributeName *)cb->sc_private;
rs->sr_attrs = an;
return SLAP_CB_CONTINUE;
}
Pierangelo Masarati
committed
static int rwm_freeself( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_RESULT ) {
assert( op->o_callback );
Pierangelo Masarati
committed
op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
op->o_callback = NULL;
Pierangelo Masarati
committed
return SLAP_CB_CONTINUE;
}
Pierangelo Masarati
committed
rwm_op_search( Operation *op, SlapReply *rs )
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
Pierangelo Masarati
committed
int rc;
dncookie dc;
struct berval fstr = BER_BVNULL;
Filter *f = NULL;
slap_callback *cb;
AttributeName *an = NULL;
char *text = NULL;
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "searchDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
text = "searchDN massage error";
Pierangelo Masarati
committed
* Rewrite the dn if needed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "searchFilterAttrDN";
#else /* ! ENABLE_REWRITE */
#endif /* ! ENABLE_REWRITE */
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
rc = rwm_filter_map_rewrite( &dc, op->ors_filter, &fstr );
if ( rc != LDAP_SUCCESS ) {
text = "searchFilter/searchFilterAttrDN massage error";
goto error_return;
}
f = str2filter_x( op, fstr.bv_val );
if ( f == NULL ) {
text = "massaged filter parse error";
goto error_return;
}
if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
ch_free( op->ors_filterstr.bv_val );
}
if( op->ors_filter ) {
filter_free_x( op, op->ors_filter );
}
op->ors_filter = f;
op->ors_filterstr = fstr;
rc = rwm_map_attrnames( &rwmap->rwm_at, &rwmap->rwm_oc,
op->ors_attrs, &an, RWM_MAP );
if ( rc != LDAP_SUCCESS ) {
text = "attribute list mapping error";
goto error_return;
cb = (slap_callback *) op->o_tmpcalloc( sizeof( slap_callback ),
1, op->o_tmpmemctx );
if ( cb == NULL ) {
rc = LDAP_NO_MEMORY;
goto error_return;
}
cb->sc_response = rwm_swap_attrs;
Pierangelo Masarati
committed
cb->sc_cleanup = rwm_freeself;
cb->sc_private = (void *)op->ors_attrs;
cb->sc_next = op->o_callback;
op->o_callback = cb;
op->ors_attrs = an;
return SLAP_CB_CONTINUE;
error_return:;
if ( an != NULL ) {
ch_free( an );
}
if ( f != NULL ) {
filter_free_x( op, f );
}
if ( !BER_BVISNULL( &fstr ) ) {
ch_free( fstr.bv_val );
}
op->o_bd->bd_info = (BackendInfo *)on->on_info;
send_ldap_error( op, rs, rc, text );
return -1;
}
static int
rwm_extended( Operation *op, SlapReply *rs )
{
Pierangelo Masarati
committed
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
int rc;
#ifdef ENABLE_REWRITE
Pierangelo Masarati
committed
rc = rwm_op_dn_massage( op, rs, "extendedDN" );
#else /* ! ENABLE_REWRITE */
rc = 1;
rc = rwm_op_dn_massage( op, rs, &rc );
#endif /* ! ENABLE_REWRITE */
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
op->o_bd->bd_info = (BackendInfo *)on->on_info;
Pierangelo Masarati
committed
send_ldap_error( op, rs, rc, "extendedDN massage error" );
return -1;
/* TODO: rewrite/map extended data ? ... */
return SLAP_CB_CONTINUE;
}
static int
rwm_matched( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
struct berval dn, mdn;
dncookie dc;
if ( rs->sr_matched == NULL ) {
return SLAP_CB_CONTINUE;
}
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = rs;
Pierangelo Masarati
committed
dc.ctx = "matchedDN";
#else /* ! ENABLE_REWRITE */
dc.tofrom = 0;
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
ber_str2bv( rs->sr_matched, 0, 0, &dn );
rc = rwm_dn_massage( &dc, &dn, &mdn, NULL );
if ( rc != LDAP_SUCCESS ) {
rs->sr_err = rc;
rs->sr_text = "Rewrite error";
return 1;
}
if ( mdn.bv_val != dn.bv_val ) {
if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
} else {
rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
}
rs->sr_matched = mdn.bv_val;
}
return SLAP_CB_CONTINUE;
}
static int
rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
dncookie dc;
int rc;
Attribute **ap;
Pierangelo Masarati
committed
* Rewrite the dn attrs, if needed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = NULL;
#else /* ! ENABLE_REWRITE */
dc.tofrom = 0;
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
/* FIXME: the entries are in the remote mapping form;
* so we need to select those attributes we are willing
* to return, and remap them accordingly */
/* FIXME: in principle, one could map an attribute
* on top of another, which already exists.
* As such, in the end there might exist more than
* one instance of an attribute.
* We should at least check if this occurs, and issue
* an error (because multiple instances of attrs in
* response are not valid), or merge the values (what
* about duplicate values?) */
for ( ap = a_first; *ap; ) {
struct ldapmapping *m;
int drop_missing;
int last;
Attribute *a;
Pierangelo Masarati
committed
if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
{
/* go on */ ;
Pierangelo Masarati
committed
} else if ( op->ors_attrs != NULL &&
!SLAP_USERATTRS( rs->sr_attr_flags ) &&
!ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
goto cleanup_attr;
}
Pierangelo Masarati
committed
if ( (*ap)->a_desc->ad_type->sat_no_user_mod
&& (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
{
goto next_attr;
}
drop_missing = rwm_mapping( &rwmap->rwm_at,
&(*ap)->a_desc->ad_cname, &m, RWM_REMAP );
if ( drop_missing || ( m != NULL && BER_BVISEMPTY( &m->m_dst ) ) ) {
goto cleanup_attr;
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
}
for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
/* just count */ ;
if ( last == 0 ) {
/* empty? for now, we leave it in place */
goto next_attr;
}
last--;
if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
|| (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
{
struct berval *bv;
for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
struct berval mapped;
rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
ch_free( bv[0].bv_val );
BER_BVZERO( &bv[0] );
if ( &(*ap)->a_vals[last] > &bv[0] ) {
bv[0] = (*ap)->a_vals[last];
BER_BVZERO( &(*ap)->a_vals[last] );
}
last--;
bv--;
} else if ( mapped.bv_val != bv[0].bv_val ) {
/*
* FIXME: after LBER_FREEing
* the value is replaced by
* ch_alloc'ed memory
*/
Pierangelo Masarati
committed
ch_free( bv[0].bv_val );
ber_dupbv( &bv[0], &mapped );
}
}
/*
* It is necessary to try to rewrite attributes with
* dn syntax because they might be used in ACLs as
* members of groups; since ACLs are applied to the
* rewritten stuff, no dn-based subject clause could
* be used at the ldap backend side (see
* http://www.OpenLDAP.org/faq/data/cache/452.html)
* The problem can be overcome by moving the dn-based
* ACLs to the target directory server, and letting
* everything pass thru the ldap backend. */
/* FIXME: handle distinguishedName-like syntaxes, like
* nameAndOptionalUID */
} else if ( (*ap)->a_desc->ad_type->sat_syntax ==
slap_schema.si_syn_distinguishedName )
{
Pierangelo Masarati
committed
#ifdef ENABLE_REWRITE
dc.ctx = "searchAttrDN";
#endif /* ENABLE_REWRITE */
rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
if ( rc != LDAP_SUCCESS ) {
goto cleanup_attr;
Pierangelo Masarati
committed
} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
#ifdef ENABLE_REWRITE
dc.ctx = "searchAttrDN";
#endif /* ENABLE_REWRITE */
Pierangelo Masarati
committed
rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
if ( rc != LDAP_SUCCESS ) {
goto cleanup_attr;
}
}
if ( m != NULL ) {
/* rewrite the attribute description */
assert( m->m_dst_ad );
(*ap)->a_desc = m->m_dst_ad;
}
next_attr:;
ap = &(*ap)->a_next;
continue;
cleanup_attr:;
a = *ap;
*ap = (*ap)->a_next;
attr_free( a );
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
return 0;
}
static int
rwm_send_entry( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldaprwmap *rwmap =
(struct ldaprwmap *)on->on_bi.bi_private;
Entry *e = NULL;
int flags;
struct berval dn = BER_BVNULL,
ndn = BER_BVNULL;
dncookie dc;
int rc;
assert( rs->sr_entry );
/*
* Rewrite the dn of the result, if needed
*/
dc.rwmap = rwmap;
#ifdef ENABLE_REWRITE
dc.conn = op->o_conn;
dc.rs = NULL;
Pierangelo Masarati
committed
dc.ctx = "searchEntryDN";
#else /* ! ENABLE_REWRITE */
dc.tofrom = 0;
dc.normalized = 0;
#endif /* ! ENABLE_REWRITE */
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
e = rs->sr_entry;
flags = rs->sr_flags;
if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
/* FIXME: all we need to duplicate are:
* - dn
* - ndn
* - attributes that are requested
* - no values if attrsonly is set
*/
e = entry_dup( e );
if ( e == NULL ) {
rc = LDAP_NO_MEMORY;
goto fail;
}
flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
}
/*
* Note: this may fail if the target host(s) schema differs
* from the one known to the meta, and a DN with unknown
* attributes is returned.
*/
rc = rwm_dn_massage( &dc, &e->e_name, &dn, &ndn );
if ( rc != LDAP_SUCCESS ) {
Pierangelo Masarati
committed
rc = 1;
goto fail;
}
if ( e->e_name.bv_val != dn.bv_val ) {
Pierangelo Masarati
committed
ch_free( e->e_name.bv_val );
ch_free( e->e_nname.bv_val );
e->e_name = dn;
e->e_nname = ndn;
}
/* TODO: map entry attribute types, objectclasses
* and dn-valued attribute values */
/* FIXME: the entries are in the remote mapping form;
* so we need to select those attributes we are willing
* to return, and remap them accordingly */
Pierangelo Masarati
committed
(void)rwm_attrs( op, rs, &e->e_attrs );
Pierangelo Masarati
committed
rs->sr_entry = e;
rs->sr_flags = flags;
return SLAP_CB_CONTINUE;
fail:;
ch_free( dn.bv_val );
}
ch_free( ndn.bv_val );
}
Pierangelo Masarati
committed
if ( e != NULL && e != rs->sr_entry ) {
static int
rwm_operational( Operation *op, SlapReply *rs )
{
/* FIXME: the entries are in the remote mapping form;
* so we need to select those attributes we are willing
* to return, and remap them accordingly */
if ( rs->sr_operational_attrs ) {
rwm_attrs( op, rs, &rs->sr_operational_attrs );
}
return SLAP_CB_CONTINUE;
}
Pierangelo Masarati
committed
#if 0
/* don't use this; it cannot be reverted, and leaves op->o_req_dn
* rewritten for subsequent operations; fine for plain suffixmassage,
* but destroys everything else */