Home | History | Annotate | Line # | Download | only in overlays
rwm.c revision 1.1.1.6
      1  1.1.1.6  christos /*	$NetBSD: rwm.c,v 1.1.1.6 2018/02/06 01:53:16 christos Exp $	*/
      2  1.1.1.2     lukem 
      3      1.1     lukem /* rwm.c - rewrite/remap operations */
      4  1.1.1.4      tron /* $OpenLDAP$ */
      5      1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6      1.1     lukem  *
      7  1.1.1.6  christos  * Copyright 2003-2017 The OpenLDAP Foundation.
      8      1.1     lukem  * Portions Copyright 2003 Pierangelo Masarati.
      9      1.1     lukem  * All rights reserved.
     10      1.1     lukem  *
     11      1.1     lukem  * Redistribution and use in source and binary forms, with or without
     12      1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     13      1.1     lukem  * Public License.
     14      1.1     lukem  *
     15      1.1     lukem  * A copy of this license is available in the file LICENSE in the
     16      1.1     lukem  * top-level directory of the distribution or, alternatively, at
     17      1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     18      1.1     lukem  */
     19      1.1     lukem 
     20  1.1.1.5  christos #include <sys/cdefs.h>
     21  1.1.1.6  christos __RCSID("$NetBSD: rwm.c,v 1.1.1.6 2018/02/06 01:53:16 christos Exp $");
     22  1.1.1.5  christos 
     23      1.1     lukem #include "portable.h"
     24      1.1     lukem 
     25      1.1     lukem #ifdef SLAPD_OVER_RWM
     26      1.1     lukem 
     27      1.1     lukem #include <stdio.h>
     28      1.1     lukem 
     29      1.1     lukem #include <ac/string.h>
     30      1.1     lukem 
     31      1.1     lukem #include "slap.h"
     32      1.1     lukem #include "config.h"
     33      1.1     lukem #include "lutil.h"
     34      1.1     lukem #include "rwm.h"
     35      1.1     lukem 
     36      1.1     lukem typedef struct rwm_op_state {
     37      1.1     lukem 	ber_tag_t r_tag;
     38      1.1     lukem 	struct berval ro_dn;
     39      1.1     lukem 	struct berval ro_ndn;
     40      1.1     lukem 	struct berval r_dn;
     41      1.1     lukem 	struct berval r_ndn;
     42  1.1.1.4      tron 	struct berval rx_dn;
     43  1.1.1.4      tron 	struct berval rx_ndn;
     44      1.1     lukem 	AttributeName *mapped_attrs;
     45      1.1     lukem 	OpRequest o_request;
     46      1.1     lukem } rwm_op_state;
     47      1.1     lukem 
     48      1.1     lukem typedef struct rwm_op_cb {
     49      1.1     lukem 	slap_callback cb;
     50      1.1     lukem 	rwm_op_state ros;
     51      1.1     lukem } rwm_op_cb;
     52      1.1     lukem 
     53      1.1     lukem static int
     54  1.1.1.2     lukem rwm_db_destroy( BackendDB *be, ConfigReply *cr );
     55      1.1     lukem 
     56  1.1.1.2     lukem static int
     57  1.1.1.2     lukem rwm_send_entry( Operation *op, SlapReply *rs );
     58      1.1     lukem 
     59  1.1.1.2     lukem static void
     60  1.1.1.2     lukem rwm_op_rollback( Operation *op, SlapReply *rs, rwm_op_state *ros )
     61  1.1.1.2     lukem {
     62  1.1.1.4      tron 	/* in case of successful extended operation cleanup
     63  1.1.1.4      tron 	 * gets called *after* (ITS#6632); this hack counts
     64  1.1.1.4      tron 	 * on others to cleanup our o_req_dn/o_req_ndn,
     65  1.1.1.4      tron 	 * while we cleanup theirs. */
     66  1.1.1.4      tron 	if ( ros->r_tag == LDAP_REQ_EXTENDED && rs->sr_err == LDAP_SUCCESS ) {
     67  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->rx_dn ) ) {
     68  1.1.1.4      tron 			ch_free( ros->rx_dn.bv_val );
     69  1.1.1.4      tron 		}
     70  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->rx_ndn ) ) {
     71  1.1.1.4      tron 			ch_free( ros->rx_ndn.bv_val );
     72  1.1.1.4      tron 		}
     73      1.1     lukem 
     74  1.1.1.4      tron 	} else {
     75  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->ro_dn ) ) {
     76  1.1.1.4      tron 			op->o_req_dn = ros->ro_dn;
     77  1.1.1.4      tron 		}
     78  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->ro_ndn ) ) {
     79  1.1.1.4      tron 			op->o_req_ndn = ros->ro_ndn;
     80  1.1.1.4      tron 		}
     81      1.1     lukem 
     82  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->r_dn )
     83  1.1.1.4      tron 			&& ros->r_dn.bv_val != ros->ro_dn.bv_val )
     84  1.1.1.4      tron 		{
     85  1.1.1.4      tron 			assert( ros->r_dn.bv_val != ros->r_ndn.bv_val );
     86  1.1.1.4      tron 			ch_free( ros->r_dn.bv_val );
     87  1.1.1.4      tron 		}
     88  1.1.1.4      tron 
     89  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->r_ndn )
     90  1.1.1.4      tron 			&& ros->r_ndn.bv_val != ros->ro_ndn.bv_val )
     91  1.1.1.4      tron 		{
     92  1.1.1.4      tron 			ch_free( ros->r_ndn.bv_val );
     93  1.1.1.4      tron 		}
     94  1.1.1.2     lukem 	}
     95      1.1     lukem 
     96  1.1.1.4      tron 	BER_BVZERO( &ros->r_dn );
     97  1.1.1.4      tron 	BER_BVZERO( &ros->r_ndn );
     98  1.1.1.2     lukem 	BER_BVZERO( &ros->ro_dn );
     99  1.1.1.2     lukem 	BER_BVZERO( &ros->ro_ndn );
    100  1.1.1.4      tron 	BER_BVZERO( &ros->rx_dn );
    101  1.1.1.4      tron 	BER_BVZERO( &ros->rx_ndn );
    102  1.1.1.2     lukem 
    103  1.1.1.2     lukem 	switch( ros->r_tag ) {
    104  1.1.1.2     lukem 	case LDAP_REQ_COMPARE:
    105  1.1.1.2     lukem 		if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
    106  1.1.1.2     lukem 			op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
    107  1.1.1.2     lukem 		op->orc_ava = ros->orc_ava;
    108  1.1.1.2     lukem 		break;
    109  1.1.1.2     lukem 	case LDAP_REQ_MODIFY:
    110  1.1.1.2     lukem 		slap_mods_free( op->orm_modlist, 1 );
    111  1.1.1.2     lukem 		op->orm_modlist = ros->orm_modlist;
    112  1.1.1.2     lukem 		break;
    113  1.1.1.2     lukem 	case LDAP_REQ_MODRDN:
    114  1.1.1.2     lukem 		if ( op->orr_newSup != ros->orr_newSup ) {
    115  1.1.1.4      tron 			if ( op->orr_newSup ) {
    116  1.1.1.4      tron 				ch_free( op->orr_newSup->bv_val );
    117  1.1.1.4      tron 				ch_free( op->orr_nnewSup->bv_val );
    118  1.1.1.4      tron 				op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
    119  1.1.1.4      tron 				op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
    120  1.1.1.4      tron 			}
    121  1.1.1.2     lukem 			op->orr_newSup = ros->orr_newSup;
    122  1.1.1.2     lukem 			op->orr_nnewSup = ros->orr_nnewSup;
    123  1.1.1.2     lukem 		}
    124  1.1.1.2     lukem 		if ( op->orr_newrdn.bv_val != ros->orr_newrdn.bv_val ) {
    125  1.1.1.2     lukem 			ch_free( op->orr_newrdn.bv_val );
    126  1.1.1.2     lukem 			ch_free( op->orr_nnewrdn.bv_val );
    127  1.1.1.2     lukem 			op->orr_newrdn = ros->orr_newrdn;
    128  1.1.1.2     lukem 			op->orr_nnewrdn = ros->orr_nnewrdn;
    129  1.1.1.2     lukem 		}
    130  1.1.1.2     lukem 		break;
    131  1.1.1.2     lukem 	case LDAP_REQ_SEARCH:
    132  1.1.1.3      adam 		op->o_tmpfree( ros->mapped_attrs, op->o_tmpmemctx );
    133  1.1.1.2     lukem 		filter_free_x( op, op->ors_filter, 1 );
    134  1.1.1.3      adam 		op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
    135  1.1.1.2     lukem 		op->ors_attrs = ros->ors_attrs;
    136  1.1.1.2     lukem 		op->ors_filter = ros->ors_filter;
    137  1.1.1.2     lukem 		op->ors_filterstr = ros->ors_filterstr;
    138  1.1.1.2     lukem 		break;
    139  1.1.1.2     lukem 	case LDAP_REQ_EXTENDED:
    140  1.1.1.2     lukem 		if ( op->ore_reqdata != ros->ore_reqdata ) {
    141  1.1.1.2     lukem 			ber_bvfree( op->ore_reqdata );
    142  1.1.1.2     lukem 			op->ore_reqdata = ros->ore_reqdata;
    143      1.1     lukem 		}
    144  1.1.1.2     lukem 		break;
    145  1.1.1.2     lukem 	case LDAP_REQ_BIND:
    146  1.1.1.2     lukem 		if ( rs->sr_err == LDAP_SUCCESS ) {
    147  1.1.1.2     lukem #if 0
    148  1.1.1.2     lukem 			ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
    149  1.1.1.2     lukem 			/* too late, c_mutex released */
    150  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY, "*** DN: \"%s\" => \"%s\"\n",
    151  1.1.1.2     lukem 				op->o_conn->c_ndn.bv_val,
    152  1.1.1.2     lukem 				op->o_req_ndn.bv_val );
    153  1.1.1.2     lukem 			ber_bvreplace( &op->o_conn->c_ndn,
    154  1.1.1.2     lukem 				&op->o_req_ndn );
    155  1.1.1.2     lukem 			ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
    156  1.1.1.2     lukem #endif
    157  1.1.1.2     lukem 		}
    158  1.1.1.2     lukem 		break;
    159  1.1.1.2     lukem 	default:	break;
    160  1.1.1.2     lukem 	}
    161  1.1.1.2     lukem }
    162  1.1.1.2     lukem 
    163  1.1.1.2     lukem static int
    164  1.1.1.2     lukem rwm_op_cleanup( Operation *op, SlapReply *rs )
    165  1.1.1.2     lukem {
    166  1.1.1.2     lukem 	slap_callback	*cb = op->o_callback;
    167  1.1.1.2     lukem 	rwm_op_state *ros = cb->sc_private;
    168  1.1.1.2     lukem 
    169  1.1.1.2     lukem 	if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
    170  1.1.1.2     lukem 		op->o_abandon || rs->sr_err == SLAPD_ABANDON )
    171  1.1.1.2     lukem 	{
    172  1.1.1.2     lukem 		rwm_op_rollback( op, rs, ros );
    173  1.1.1.2     lukem 
    174      1.1     lukem 		op->o_callback = op->o_callback->sc_next;
    175      1.1     lukem 		op->o_tmpfree( cb, op->o_tmpmemctx );
    176      1.1     lukem 	}
    177      1.1     lukem 
    178      1.1     lukem 	return SLAP_CB_CONTINUE;
    179      1.1     lukem }
    180      1.1     lukem 
    181      1.1     lukem static rwm_op_cb *
    182  1.1.1.4      tron rwm_callback_get( Operation *op )
    183      1.1     lukem {
    184  1.1.1.4      tron 	rwm_op_cb	*roc;
    185      1.1     lukem 
    186  1.1.1.5  christos 	roc = op->o_tmpcalloc( 1, sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
    187      1.1     lukem 	roc->cb.sc_cleanup = rwm_op_cleanup;
    188      1.1     lukem 	roc->cb.sc_response = NULL;
    189      1.1     lukem 	roc->cb.sc_next = op->o_callback;
    190      1.1     lukem 	roc->cb.sc_private = &roc->ros;
    191      1.1     lukem 	roc->ros.r_tag = op->o_tag;
    192      1.1     lukem 	roc->ros.ro_dn = op->o_req_dn;
    193      1.1     lukem 	roc->ros.ro_ndn = op->o_req_ndn;
    194      1.1     lukem 	BER_BVZERO( &roc->ros.r_dn );
    195      1.1     lukem 	BER_BVZERO( &roc->ros.r_ndn );
    196  1.1.1.4      tron 	BER_BVZERO( &roc->ros.rx_dn );
    197  1.1.1.4      tron 	BER_BVZERO( &roc->ros.rx_ndn );
    198  1.1.1.4      tron 	roc->ros.mapped_attrs = NULL;
    199  1.1.1.4      tron 	roc->ros.o_request = op->o_request;
    200      1.1     lukem 
    201      1.1     lukem 	return roc;
    202      1.1     lukem }
    203      1.1     lukem 
    204      1.1     lukem 
    205      1.1     lukem static int
    206      1.1     lukem rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
    207      1.1     lukem 	rwm_op_state *ros )
    208      1.1     lukem {
    209      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    210      1.1     lukem 	struct ldaprwmap	*rwmap =
    211      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    212      1.1     lukem 
    213      1.1     lukem 	struct berval		dn = BER_BVNULL,
    214      1.1     lukem 				ndn = BER_BVNULL;
    215      1.1     lukem 	int			rc = 0;
    216      1.1     lukem 	dncookie		dc;
    217      1.1     lukem 
    218      1.1     lukem 	/*
    219      1.1     lukem 	 * Rewrite the dn if needed
    220      1.1     lukem 	 */
    221      1.1     lukem 	dc.rwmap = rwmap;
    222      1.1     lukem 	dc.conn = op->o_conn;
    223      1.1     lukem 	dc.rs = rs;
    224      1.1     lukem 	dc.ctx = (char *)cookie;
    225      1.1     lukem 
    226      1.1     lukem 	/* NOTE: in those cases where only the ndn is available,
    227      1.1     lukem 	 * and the caller sets op->o_req_dn = op->o_req_ndn,
    228      1.1     lukem 	 * only rewrite the op->o_req_ndn and use it as
    229      1.1     lukem 	 * op->o_req_dn as well */
    230      1.1     lukem 	ndn = op->o_req_ndn;
    231      1.1     lukem 	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
    232      1.1     lukem 		dn = op->o_req_dn;
    233      1.1     lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
    234      1.1     lukem 	} else {
    235      1.1     lukem 		rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
    236      1.1     lukem 	}
    237      1.1     lukem 
    238      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    239      1.1     lukem 		return rc;
    240      1.1     lukem 	}
    241      1.1     lukem 
    242      1.1     lukem 	if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
    243      1.1     lukem 			|| ndn.bv_val == op->o_req_ndn.bv_val )
    244      1.1     lukem 	{
    245      1.1     lukem 		return LDAP_SUCCESS;
    246      1.1     lukem 	}
    247      1.1     lukem 
    248      1.1     lukem 	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
    249      1.1     lukem 		op->o_req_dn = dn;
    250  1.1.1.2     lukem 		assert( BER_BVISNULL( &ros->r_dn ) );
    251      1.1     lukem 		ros->r_dn = dn;
    252      1.1     lukem 	} else {
    253      1.1     lukem 		op->o_req_dn = ndn;
    254      1.1     lukem 	}
    255      1.1     lukem 	op->o_req_ndn = ndn;
    256  1.1.1.2     lukem 	assert( BER_BVISNULL( &ros->r_ndn ) );
    257      1.1     lukem 	ros->r_ndn = ndn;
    258      1.1     lukem 
    259  1.1.1.4      tron 	if ( ros->r_tag == LDAP_REQ_EXTENDED ) {
    260  1.1.1.4      tron 		ros->rx_dn = ros->r_dn;
    261  1.1.1.4      tron 		ros->rx_ndn = ros->r_ndn;
    262  1.1.1.4      tron 	}
    263  1.1.1.4      tron 
    264      1.1     lukem 	return LDAP_SUCCESS;
    265      1.1     lukem }
    266      1.1     lukem 
    267      1.1     lukem static int
    268      1.1     lukem rwm_op_add( Operation *op, SlapReply *rs )
    269      1.1     lukem {
    270      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    271      1.1     lukem 	struct ldaprwmap	*rwmap =
    272      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    273      1.1     lukem 
    274      1.1     lukem 	int			rc,
    275      1.1     lukem 				i;
    276      1.1     lukem 	Attribute		**ap = NULL;
    277      1.1     lukem 	char			*olddn = op->o_req_dn.bv_val;
    278      1.1     lukem 	int			isupdate;
    279      1.1     lukem 
    280  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    281      1.1     lukem 
    282      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
    283      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    284      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    285      1.1     lukem 		send_ldap_error( op, rs, rc, "addDN massage error" );
    286      1.1     lukem 		return -1;
    287      1.1     lukem 	}
    288      1.1     lukem 
    289      1.1     lukem 	if ( olddn != op->o_req_dn.bv_val ) {
    290      1.1     lukem 		ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
    291      1.1     lukem 		ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
    292      1.1     lukem 	}
    293      1.1     lukem 
    294      1.1     lukem 	/* Count number of attributes in entry */
    295      1.1     lukem 	isupdate = be_shadow_update( op );
    296      1.1     lukem 	for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
    297      1.1     lukem 		Attribute	*a;
    298      1.1     lukem 
    299      1.1     lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
    300      1.1     lukem 				(*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
    301      1.1     lukem 		{
    302      1.1     lukem 			int		j, last;
    303      1.1     lukem 
    304      1.1     lukem 			last = (*ap)->a_numvals - 1;
    305      1.1     lukem 			for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
    306      1.1     lukem 				struct ldapmapping	*mapping = NULL;
    307      1.1     lukem 
    308      1.1     lukem 				( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
    309      1.1     lukem 						&mapping, RWM_MAP );
    310      1.1     lukem 				if ( mapping == NULL ) {
    311      1.1     lukem 					if ( rwmap->rwm_at.drop_missing ) {
    312      1.1     lukem 						/* FIXME: we allow to remove objectClasses as well;
    313      1.1     lukem 						 * if the resulting entry is inconsistent, that's
    314      1.1     lukem 						 * the relayed database's business...
    315      1.1     lukem 						 */
    316      1.1     lukem 						ch_free( (*ap)->a_vals[ j ].bv_val );
    317      1.1     lukem 						if ( last > j ) {
    318      1.1     lukem 							(*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
    319      1.1     lukem 						}
    320      1.1     lukem 						BER_BVZERO( &(*ap)->a_vals[ last ] );
    321      1.1     lukem 						(*ap)->a_numvals--;
    322      1.1     lukem 						last--;
    323      1.1     lukem 						j--;
    324      1.1     lukem 					}
    325      1.1     lukem 
    326      1.1     lukem 				} else {
    327      1.1     lukem 					ch_free( (*ap)->a_vals[ j ].bv_val );
    328      1.1     lukem 					ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
    329      1.1     lukem 				}
    330      1.1     lukem 			}
    331      1.1     lukem 
    332      1.1     lukem 		} else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
    333      1.1     lukem 		{
    334      1.1     lukem 			goto next_attr;
    335      1.1     lukem 
    336      1.1     lukem 		} else {
    337      1.1     lukem 			struct ldapmapping	*mapping = NULL;
    338      1.1     lukem 
    339      1.1     lukem 			( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
    340      1.1     lukem 					&mapping, RWM_MAP );
    341      1.1     lukem 			if ( mapping == NULL ) {
    342      1.1     lukem 				if ( rwmap->rwm_at.drop_missing ) {
    343      1.1     lukem 					goto cleanup_attr;
    344      1.1     lukem 				}
    345      1.1     lukem 			}
    346      1.1     lukem 
    347      1.1     lukem 			if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    348      1.1     lukem 					|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    349      1.1     lukem 			{
    350      1.1     lukem 				/*
    351      1.1     lukem 				 * FIXME: rewrite could fail; in this case
    352      1.1     lukem 				 * the operation should give up, right?
    353      1.1     lukem 				 */
    354      1.1     lukem 				rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
    355      1.1     lukem 						(*ap)->a_vals,
    356      1.1     lukem 						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
    357      1.1     lukem 				if ( rc ) {
    358      1.1     lukem 					goto cleanup_attr;
    359      1.1     lukem 				}
    360      1.1     lukem 
    361      1.1     lukem 			} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
    362      1.1     lukem 				rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
    363      1.1     lukem 						(*ap)->a_vals,
    364      1.1     lukem 						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
    365      1.1     lukem 				if ( rc != LDAP_SUCCESS ) {
    366      1.1     lukem 					goto cleanup_attr;
    367      1.1     lukem 				}
    368      1.1     lukem 			}
    369      1.1     lukem 
    370      1.1     lukem 			if ( mapping != NULL ) {
    371      1.1     lukem 				assert( mapping->m_dst_ad != NULL );
    372      1.1     lukem 				(*ap)->a_desc = mapping->m_dst_ad;
    373      1.1     lukem 			}
    374      1.1     lukem 		}
    375      1.1     lukem 
    376      1.1     lukem next_attr:;
    377      1.1     lukem 		ap = &(*ap)->a_next;
    378      1.1     lukem 		continue;
    379      1.1     lukem 
    380      1.1     lukem cleanup_attr:;
    381      1.1     lukem 		/* FIXME: leaking attribute/values? */
    382      1.1     lukem 		a = *ap;
    383      1.1     lukem 
    384      1.1     lukem 		*ap = (*ap)->a_next;
    385      1.1     lukem 		attr_free( a );
    386      1.1     lukem 	}
    387      1.1     lukem 
    388      1.1     lukem 	op->o_callback = &roc->cb;
    389      1.1     lukem 
    390      1.1     lukem 	return SLAP_CB_CONTINUE;
    391      1.1     lukem }
    392      1.1     lukem 
    393      1.1     lukem static int
    394      1.1     lukem rwm_conn_init( BackendDB *be, Connection *conn )
    395      1.1     lukem {
    396      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
    397      1.1     lukem 	struct ldaprwmap	*rwmap =
    398      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    399      1.1     lukem 
    400      1.1     lukem 	( void )rewrite_session_init( rwmap->rwm_rw, conn );
    401      1.1     lukem 
    402      1.1     lukem 	return SLAP_CB_CONTINUE;
    403      1.1     lukem }
    404      1.1     lukem 
    405      1.1     lukem static int
    406      1.1     lukem rwm_conn_destroy( BackendDB *be, Connection *conn )
    407      1.1     lukem {
    408      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
    409      1.1     lukem 	struct ldaprwmap	*rwmap =
    410      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    411      1.1     lukem 
    412      1.1     lukem 	( void )rewrite_session_delete( rwmap->rwm_rw, conn );
    413      1.1     lukem 
    414      1.1     lukem 	return SLAP_CB_CONTINUE;
    415      1.1     lukem }
    416      1.1     lukem 
    417      1.1     lukem static int
    418      1.1     lukem rwm_op_bind( Operation *op, SlapReply *rs )
    419      1.1     lukem {
    420      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    421      1.1     lukem 	int			rc;
    422      1.1     lukem 
    423  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    424      1.1     lukem 
    425      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
    426      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    427      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    428      1.1     lukem 		send_ldap_error( op, rs, rc, "bindDN massage error" );
    429      1.1     lukem 		return -1;
    430      1.1     lukem 	}
    431      1.1     lukem 
    432  1.1.1.2     lukem 	overlay_callback_after_backover( op, &roc->cb, 1 );
    433      1.1     lukem 
    434      1.1     lukem 	return SLAP_CB_CONTINUE;
    435      1.1     lukem }
    436      1.1     lukem 
    437      1.1     lukem static int
    438      1.1     lukem rwm_op_unbind( Operation *op, SlapReply *rs )
    439      1.1     lukem {
    440      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    441      1.1     lukem 	struct ldaprwmap	*rwmap =
    442      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    443      1.1     lukem 
    444      1.1     lukem 	rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
    445      1.1     lukem 
    446      1.1     lukem 	return SLAP_CB_CONTINUE;
    447      1.1     lukem }
    448      1.1     lukem 
    449      1.1     lukem static int
    450      1.1     lukem rwm_op_compare( Operation *op, SlapReply *rs )
    451      1.1     lukem {
    452      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    453      1.1     lukem 	struct ldaprwmap	*rwmap =
    454      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    455      1.1     lukem 
    456      1.1     lukem 	int			rc;
    457      1.1     lukem 	struct berval		mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
    458      1.1     lukem 
    459  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    460      1.1     lukem 
    461      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
    462      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    463      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    464      1.1     lukem 		send_ldap_error( op, rs, rc, "compareDN massage error" );
    465      1.1     lukem 		return -1;
    466      1.1     lukem 	}
    467      1.1     lukem 
    468      1.1     lukem 	/* if the attribute is an objectClass, try to remap its value */
    469      1.1     lukem 	if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
    470      1.1     lukem 			|| op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
    471      1.1     lukem 	{
    472      1.1     lukem 		rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
    473      1.1     lukem 				&mapped_vals[0], RWM_MAP );
    474      1.1     lukem 		if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
    475      1.1     lukem 		{
    476      1.1     lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    477      1.1     lukem 			send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
    478      1.1     lukem 			return -1;
    479      1.1     lukem 
    480      1.1     lukem 		} else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
    481      1.1     lukem 			ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
    482      1.1     lukem 				op->o_tmpmemctx );
    483      1.1     lukem 		}
    484      1.1     lukem 
    485      1.1     lukem 	} else {
    486      1.1     lukem 		struct ldapmapping	*mapping = NULL;
    487      1.1     lukem 		AttributeDescription	*ad = op->orc_ava->aa_desc;
    488      1.1     lukem 
    489      1.1     lukem 		( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
    490      1.1     lukem 				&mapping, RWM_MAP );
    491      1.1     lukem 		if ( mapping == NULL ) {
    492      1.1     lukem 			if ( rwmap->rwm_at.drop_missing ) {
    493      1.1     lukem 				op->o_bd->bd_info = (BackendInfo *)on->on_info;
    494      1.1     lukem 				send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
    495      1.1     lukem 				return -1;
    496      1.1     lukem 			}
    497      1.1     lukem 
    498      1.1     lukem 		} else {
    499      1.1     lukem 			assert( mapping->m_dst_ad != NULL );
    500      1.1     lukem 			ad = mapping->m_dst_ad;
    501      1.1     lukem 		}
    502      1.1     lukem 
    503      1.1     lukem 		if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    504      1.1     lukem 				|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    505      1.1     lukem 		{
    506      1.1     lukem 			struct berval	*mapped_valsp[2];
    507      1.1     lukem 
    508      1.1     lukem 			mapped_valsp[0] = &mapped_vals[0];
    509      1.1     lukem 			mapped_valsp[1] = &mapped_vals[1];
    510      1.1     lukem 
    511      1.1     lukem 			mapped_vals[0] = op->orc_ava->aa_value;
    512      1.1     lukem 
    513      1.1     lukem 			rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
    514      1.1     lukem 
    515      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
    516      1.1     lukem 				op->o_bd->bd_info = (BackendInfo *)on->on_info;
    517      1.1     lukem 				send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
    518      1.1     lukem 				return -1;
    519      1.1     lukem 			}
    520      1.1     lukem 
    521      1.1     lukem 			if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
    522      1.1     lukem 				/* NOTE: if we get here, rwm_dnattr_rewrite()
    523      1.1     lukem 				 * already freed the old value, so now
    524      1.1     lukem 				 * it's invalid */
    525      1.1     lukem 				ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
    526      1.1     lukem 					op->o_tmpmemctx );
    527      1.1     lukem 				ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
    528      1.1     lukem 			}
    529      1.1     lukem 		}
    530      1.1     lukem 		op->orc_ava->aa_desc = ad;
    531      1.1     lukem 	}
    532      1.1     lukem 
    533      1.1     lukem 	op->o_callback = &roc->cb;
    534      1.1     lukem 
    535      1.1     lukem 	return SLAP_CB_CONTINUE;
    536      1.1     lukem }
    537      1.1     lukem 
    538      1.1     lukem static int
    539      1.1     lukem rwm_op_delete( Operation *op, SlapReply *rs )
    540      1.1     lukem {
    541      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    542      1.1     lukem 	int			rc;
    543      1.1     lukem 
    544  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    545      1.1     lukem 
    546      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
    547      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    548      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    549      1.1     lukem 		send_ldap_error( op, rs, rc, "deleteDN massage error" );
    550      1.1     lukem 		return -1;
    551      1.1     lukem 	}
    552      1.1     lukem 
    553      1.1     lukem 	op->o_callback = &roc->cb;
    554      1.1     lukem 
    555      1.1     lukem 	return SLAP_CB_CONTINUE;
    556      1.1     lukem }
    557      1.1     lukem 
    558      1.1     lukem static int
    559      1.1     lukem rwm_op_modify( Operation *op, SlapReply *rs )
    560      1.1     lukem {
    561      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    562      1.1     lukem 	struct ldaprwmap	*rwmap =
    563      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    564      1.1     lukem 
    565      1.1     lukem 	int			isupdate;
    566      1.1     lukem 	Modifications		**mlp;
    567      1.1     lukem 	int			rc;
    568      1.1     lukem 
    569  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    570      1.1     lukem 
    571      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
    572      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    573      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    574      1.1     lukem 		send_ldap_error( op, rs, rc, "modifyDN massage error" );
    575      1.1     lukem 		return -1;
    576      1.1     lukem 	}
    577      1.1     lukem 
    578      1.1     lukem 	isupdate = be_shadow_update( op );
    579      1.1     lukem 	for ( mlp = &op->orm_modlist; *mlp; ) {
    580      1.1     lukem 		int			is_oc = 0;
    581      1.1     lukem 		Modifications		*ml = *mlp;
    582      1.1     lukem 		struct ldapmapping	*mapping = NULL;
    583      1.1     lukem 
    584      1.1     lukem 		/* ml points to a temporary mod until needs duplication */
    585      1.1     lukem 		if ( ml->sml_desc == slap_schema.si_ad_objectClass
    586      1.1     lukem 				|| ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
    587      1.1     lukem 		{
    588      1.1     lukem 			is_oc = 1;
    589      1.1     lukem 
    590      1.1     lukem 		} else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
    591      1.1     lukem 		{
    592      1.1     lukem 			ml = ch_malloc( sizeof( Modifications ) );
    593      1.1     lukem 			*ml = **mlp;
    594      1.1     lukem 			if ( (*mlp)->sml_values ) {
    595      1.1     lukem 				ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
    596      1.1     lukem 				if ( (*mlp)->sml_nvalues ) {
    597      1.1     lukem 					ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
    598      1.1     lukem 				}
    599      1.1     lukem 			}
    600      1.1     lukem 			*mlp = ml;
    601      1.1     lukem 			goto next_mod;
    602      1.1     lukem 
    603      1.1     lukem 		} else {
    604      1.1     lukem 			int			drop_missing;
    605      1.1     lukem 
    606      1.1     lukem 			drop_missing = rwm_mapping( &rwmap->rwm_at,
    607      1.1     lukem 					&ml->sml_desc->ad_cname,
    608      1.1     lukem 					&mapping, RWM_MAP );
    609      1.1     lukem 			if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
    610      1.1     lukem 			{
    611  1.1.1.4      tron 				goto skip_mod;
    612      1.1     lukem 			}
    613      1.1     lukem 		}
    614      1.1     lukem 
    615      1.1     lukem 		/* duplicate the modlist */
    616      1.1     lukem 		ml = ch_malloc( sizeof( Modifications ));
    617      1.1     lukem 		*ml = **mlp;
    618      1.1     lukem 		*mlp = ml;
    619      1.1     lukem 
    620      1.1     lukem 		if ( ml->sml_values != NULL ) {
    621      1.1     lukem 			int i, num;
    622      1.1     lukem 			struct berval *bva;
    623      1.1     lukem 
    624      1.1     lukem 			for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
    625      1.1     lukem 				/* count values */ ;
    626      1.1     lukem 
    627      1.1     lukem 			bva = ch_malloc( (num+1) * sizeof( struct berval ));
    628      1.1     lukem 			for (i=0; i<num; i++)
    629      1.1     lukem 				ber_dupbv( &bva[i], &ml->sml_values[i] );
    630      1.1     lukem 			BER_BVZERO( &bva[i] );
    631      1.1     lukem 			ml->sml_values = bva;
    632      1.1     lukem 
    633      1.1     lukem 			if ( ml->sml_nvalues ) {
    634      1.1     lukem 				bva = ch_malloc( (num+1) * sizeof( struct berval ));
    635      1.1     lukem 				for (i=0; i<num; i++)
    636      1.1     lukem 					ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
    637      1.1     lukem 				BER_BVZERO( &bva[i] );
    638      1.1     lukem 				ml->sml_nvalues = bva;
    639      1.1     lukem 			}
    640      1.1     lukem 
    641      1.1     lukem 			if ( is_oc ) {
    642      1.1     lukem 				int	last, j;
    643      1.1     lukem 
    644      1.1     lukem 				last = num-1;
    645      1.1     lukem 
    646      1.1     lukem 				for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
    647      1.1     lukem 					struct ldapmapping	*oc_mapping = NULL;
    648      1.1     lukem 
    649      1.1     lukem 					( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
    650      1.1     lukem 							&oc_mapping, RWM_MAP );
    651      1.1     lukem 					if ( oc_mapping == NULL ) {
    652      1.1     lukem 						if ( rwmap->rwm_at.drop_missing ) {
    653      1.1     lukem 							/* FIXME: we allow to remove objectClasses as well;
    654      1.1     lukem 							 * if the resulting entry is inconsistent, that's
    655      1.1     lukem 							 * the relayed database's business...
    656      1.1     lukem 							 */
    657      1.1     lukem 							if ( last > j ) {
    658      1.1     lukem 								ch_free( ml->sml_values[ j ].bv_val );
    659      1.1     lukem 								ml->sml_values[ j ] = ml->sml_values[ last ];
    660      1.1     lukem 							}
    661      1.1     lukem 							BER_BVZERO( &ml->sml_values[ last ] );
    662      1.1     lukem 							last--;
    663      1.1     lukem 							j--;
    664      1.1     lukem 						}
    665      1.1     lukem 
    666      1.1     lukem 					} else {
    667      1.1     lukem 						ch_free( ml->sml_values[ j ].bv_val );
    668      1.1     lukem 						ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
    669      1.1     lukem 					}
    670      1.1     lukem 				}
    671      1.1     lukem 
    672      1.1     lukem 			} else {
    673      1.1     lukem 				if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    674      1.1     lukem 						|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    675      1.1     lukem 				{
    676      1.1     lukem 					rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
    677      1.1     lukem 							ml->sml_values,
    678      1.1     lukem 							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
    679      1.1     lukem 
    680      1.1     lukem 				} else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
    681      1.1     lukem 					rc = rwm_referral_rewrite( op, rs,
    682      1.1     lukem 							"referralAttrDN",
    683      1.1     lukem 							ml->sml_values,
    684      1.1     lukem 							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
    685      1.1     lukem 					if ( rc != LDAP_SUCCESS ) {
    686      1.1     lukem 						goto cleanup_mod;
    687      1.1     lukem 					}
    688      1.1     lukem 				}
    689      1.1     lukem 
    690      1.1     lukem 				if ( rc != LDAP_SUCCESS ) {
    691      1.1     lukem 					goto cleanup_mod;
    692      1.1     lukem 				}
    693      1.1     lukem 			}
    694      1.1     lukem 		}
    695      1.1     lukem 
    696      1.1     lukem next_mod:;
    697      1.1     lukem 		if ( mapping != NULL ) {
    698      1.1     lukem 			/* use new attribute description */
    699      1.1     lukem 			assert( mapping->m_dst_ad != NULL );
    700      1.1     lukem 			ml->sml_desc = mapping->m_dst_ad;
    701      1.1     lukem 		}
    702      1.1     lukem 
    703      1.1     lukem 		mlp = &ml->sml_next;
    704      1.1     lukem 		continue;
    705      1.1     lukem 
    706  1.1.1.4      tron skip_mod:;
    707  1.1.1.4      tron 		*mlp = (*mlp)->sml_next;
    708  1.1.1.4      tron 		continue;
    709  1.1.1.4      tron 
    710      1.1     lukem cleanup_mod:;
    711      1.1     lukem 		ml = *mlp;
    712      1.1     lukem 		*mlp = (*mlp)->sml_next;
    713      1.1     lukem 		slap_mod_free( &ml->sml_mod, 0 );
    714      1.1     lukem 		free( ml );
    715      1.1     lukem 	}
    716      1.1     lukem 
    717      1.1     lukem 	op->o_callback = &roc->cb;
    718      1.1     lukem 
    719      1.1     lukem 	return SLAP_CB_CONTINUE;
    720      1.1     lukem }
    721      1.1     lukem 
    722      1.1     lukem static int
    723      1.1     lukem rwm_op_modrdn( Operation *op, SlapReply *rs )
    724      1.1     lukem {
    725      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    726      1.1     lukem 	struct ldaprwmap	*rwmap =
    727      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    728      1.1     lukem 
    729      1.1     lukem 	int			rc;
    730  1.1.1.2     lukem 	dncookie		dc;
    731      1.1     lukem 
    732  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    733      1.1     lukem 
    734      1.1     lukem 	if ( op->orr_newSup ) {
    735      1.1     lukem 		struct berval	nnewSup = BER_BVNULL;
    736      1.1     lukem 		struct berval	newSup = BER_BVNULL;
    737      1.1     lukem 
    738      1.1     lukem 		/*
    739      1.1     lukem 		 * Rewrite the new superior, if defined and required
    740      1.1     lukem 	 	 */
    741      1.1     lukem 		dc.rwmap = rwmap;
    742      1.1     lukem 		dc.conn = op->o_conn;
    743      1.1     lukem 		dc.rs = rs;
    744      1.1     lukem 		dc.ctx = "newSuperiorDN";
    745      1.1     lukem 		newSup = *op->orr_newSup;
    746      1.1     lukem 		nnewSup = *op->orr_nnewSup;
    747      1.1     lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
    748      1.1     lukem 		if ( rc != LDAP_SUCCESS ) {
    749      1.1     lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    750      1.1     lukem 			send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
    751      1.1     lukem 			return -1;
    752      1.1     lukem 		}
    753      1.1     lukem 
    754      1.1     lukem 		if ( op->orr_newSup->bv_val != newSup.bv_val ) {
    755      1.1     lukem 			op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
    756      1.1     lukem 				op->o_tmpmemctx );
    757      1.1     lukem 			op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
    758      1.1     lukem 				op->o_tmpmemctx );
    759      1.1     lukem 			*op->orr_newSup = newSup;
    760      1.1     lukem 			*op->orr_nnewSup = nnewSup;
    761      1.1     lukem 		}
    762      1.1     lukem 	}
    763      1.1     lukem 
    764      1.1     lukem 	/*
    765  1.1.1.2     lukem 	 * Rewrite the newRDN, if needed
    766  1.1.1.2     lukem  	 */
    767  1.1.1.2     lukem 	{
    768  1.1.1.2     lukem 		struct berval	newrdn = BER_BVNULL;
    769  1.1.1.2     lukem 		struct berval	nnewrdn = BER_BVNULL;
    770  1.1.1.2     lukem 
    771  1.1.1.2     lukem 		dc.rwmap = rwmap;
    772  1.1.1.2     lukem 		dc.conn = op->o_conn;
    773  1.1.1.2     lukem 		dc.rs = rs;
    774  1.1.1.2     lukem 		dc.ctx = "newRDN";
    775  1.1.1.2     lukem 		newrdn = op->orr_newrdn;
    776  1.1.1.2     lukem 		nnewrdn = op->orr_nnewrdn;
    777  1.1.1.2     lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, &op->orr_newrdn, &newrdn, &nnewrdn );
    778  1.1.1.2     lukem 		if ( rc != LDAP_SUCCESS ) {
    779  1.1.1.2     lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    780  1.1.1.2     lukem 			send_ldap_error( op, rs, rc, "newRDN massage error" );
    781  1.1.1.2     lukem 			goto err;
    782  1.1.1.2     lukem 		}
    783  1.1.1.2     lukem 
    784  1.1.1.2     lukem 		if ( op->orr_newrdn.bv_val != newrdn.bv_val ) {
    785  1.1.1.2     lukem 			op->orr_newrdn = newrdn;
    786  1.1.1.2     lukem 			op->orr_nnewrdn = nnewrdn;
    787  1.1.1.2     lukem 		}
    788  1.1.1.2     lukem 	}
    789  1.1.1.2     lukem 
    790  1.1.1.2     lukem 	/*
    791      1.1     lukem 	 * Rewrite the dn, if needed
    792      1.1     lukem  	 */
    793      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
    794      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    795      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    796      1.1     lukem 		send_ldap_error( op, rs, rc, "renameDN massage error" );
    797  1.1.1.2     lukem 		goto err;
    798  1.1.1.2     lukem 	}
    799  1.1.1.2     lukem 
    800  1.1.1.2     lukem 	op->o_callback = &roc->cb;
    801  1.1.1.2     lukem 
    802  1.1.1.2     lukem 	rc = SLAP_CB_CONTINUE;
    803  1.1.1.2     lukem 
    804  1.1.1.2     lukem 	if ( 0 ) {
    805  1.1.1.2     lukem err:;
    806      1.1     lukem 		if ( op->orr_newSup != roc->ros.orr_newSup ) {
    807      1.1     lukem 			ch_free( op->orr_newSup->bv_val );
    808      1.1     lukem 			ch_free( op->orr_nnewSup->bv_val );
    809      1.1     lukem 			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
    810      1.1     lukem 			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
    811      1.1     lukem 			op->orr_newSup = roc->ros.orr_newSup;
    812      1.1     lukem 			op->orr_nnewSup = roc->ros.orr_nnewSup;
    813      1.1     lukem 		}
    814      1.1     lukem 
    815  1.1.1.2     lukem 		if ( op->orr_newrdn.bv_val != roc->ros.orr_newrdn.bv_val ) {
    816  1.1.1.2     lukem 			ch_free( op->orr_newrdn.bv_val );
    817  1.1.1.2     lukem 			ch_free( op->orr_nnewrdn.bv_val );
    818  1.1.1.2     lukem 			op->orr_newrdn = roc->ros.orr_newrdn;
    819  1.1.1.2     lukem 			op->orr_nnewrdn = roc->ros.orr_nnewrdn;
    820  1.1.1.2     lukem 		}
    821  1.1.1.2     lukem 	}
    822      1.1     lukem 
    823  1.1.1.2     lukem 	return rc;
    824      1.1     lukem }
    825      1.1     lukem 
    826      1.1     lukem 
    827      1.1     lukem static int
    828      1.1     lukem rwm_swap_attrs( Operation *op, SlapReply *rs )
    829      1.1     lukem {
    830      1.1     lukem 	slap_callback	*cb = op->o_callback;
    831      1.1     lukem 	rwm_op_state *ros = cb->sc_private;
    832      1.1     lukem 
    833      1.1     lukem 	rs->sr_attrs = ros->ors_attrs;
    834      1.1     lukem 
    835      1.1     lukem 	/* other overlays might have touched op->ors_attrs,
    836      1.1     lukem 	 * so we restore the original version here, otherwise
    837      1.1     lukem 	 * attribute-mapping might fail */
    838      1.1     lukem 	op->ors_attrs = ros->mapped_attrs;
    839      1.1     lukem 
    840      1.1     lukem  	return SLAP_CB_CONTINUE;
    841      1.1     lukem }
    842      1.1     lukem 
    843  1.1.1.2     lukem /*
    844  1.1.1.2     lukem  * NOTE: this implementation of get/release entry is probably far from
    845  1.1.1.2     lukem  * optimal.  The rationale consists in intercepting the request directed
    846  1.1.1.2     lukem  * to the underlying database, in order to rewrite/remap the request,
    847  1.1.1.2     lukem  * perform it using the modified data, duplicate the resulting entry
    848  1.1.1.2     lukem  * and finally free it when release is called.
    849  1.1.1.2     lukem  * This implies that subsequent overlays are not called, as the request
    850  1.1.1.2     lukem  * is directly shunted to the underlying database.
    851  1.1.1.2     lukem  */
    852  1.1.1.2     lukem static int
    853  1.1.1.2     lukem rwm_entry_release_rw( Operation *op, Entry *e, int rw )
    854  1.1.1.2     lukem {
    855  1.1.1.2     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    856  1.1.1.2     lukem 
    857  1.1.1.2     lukem 	/* can't be ours */
    858  1.1.1.2     lukem 	if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
    859  1.1.1.2     lukem 		return SLAP_CB_CONTINUE;
    860  1.1.1.2     lukem 	}
    861  1.1.1.2     lukem 
    862  1.1.1.2     lukem 	/* just free entry if (probably) ours */
    863  1.1.1.2     lukem 	if ( e->e_private == NULL && BER_BVISNULL( &e->e_bv ) ) {
    864  1.1.1.2     lukem 		entry_free( e );
    865  1.1.1.2     lukem 		return LDAP_SUCCESS;
    866  1.1.1.2     lukem 	}
    867  1.1.1.2     lukem 
    868  1.1.1.2     lukem 	return SLAP_CB_CONTINUE;
    869  1.1.1.2     lukem }
    870  1.1.1.2     lukem 
    871  1.1.1.2     lukem static int
    872  1.1.1.2     lukem rwm_entry_get_rw( Operation *op, struct berval *ndn,
    873  1.1.1.2     lukem 	ObjectClass *oc, AttributeDescription *at, int rw, Entry **ep )
    874  1.1.1.2     lukem {
    875  1.1.1.2     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    876  1.1.1.2     lukem 	int			rc;
    877  1.1.1.2     lukem 	BackendDB		db;
    878  1.1.1.2     lukem 	Operation		op2;
    879  1.1.1.2     lukem 	SlapReply		rs = { REP_SEARCH };
    880  1.1.1.2     lukem 
    881  1.1.1.2     lukem 	rwm_op_state		ros = { 0 };
    882  1.1.1.2     lukem 	struct berval		mndn = BER_BVNULL;
    883  1.1.1.2     lukem 
    884  1.1.1.2     lukem 	if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
    885  1.1.1.2     lukem 		return SLAP_CB_CONTINUE;
    886  1.1.1.2     lukem 	}
    887  1.1.1.2     lukem 
    888  1.1.1.2     lukem 	/* massage DN */
    889  1.1.1.2     lukem 	op2.o_tag = LDAP_REQ_SEARCH;
    890  1.1.1.2     lukem 	op2 = *op;
    891  1.1.1.2     lukem 	op2.o_req_dn = *ndn;
    892  1.1.1.2     lukem 	op2.o_req_ndn = *ndn;
    893  1.1.1.2     lukem 	rc = rwm_op_dn_massage( &op2, &rs, "searchDN", &ros );
    894  1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS ) {
    895  1.1.1.2     lukem 		return LDAP_OTHER;
    896  1.1.1.2     lukem 	}
    897  1.1.1.2     lukem 
    898  1.1.1.2     lukem 	mndn = BER_BVISNULL( &ros.r_ndn ) ? *ndn : ros.r_ndn;
    899  1.1.1.2     lukem 
    900  1.1.1.2     lukem 	/* map attribute & objectClass */
    901  1.1.1.2     lukem 	if ( at != NULL ) {
    902  1.1.1.2     lukem 	}
    903  1.1.1.2     lukem 
    904  1.1.1.2     lukem 	if ( oc != NULL ) {
    905  1.1.1.2     lukem 	}
    906  1.1.1.2     lukem 
    907  1.1.1.2     lukem 	/* fetch entry */
    908  1.1.1.2     lukem 	db = *op->o_bd;
    909  1.1.1.2     lukem 	op2.o_bd = &db;
    910  1.1.1.2     lukem 	op2.o_bd->bd_info = (BackendInfo *)on->on_info->oi_orig;
    911  1.1.1.2     lukem 	op2.ors_attrs = slap_anlist_all_attributes;
    912  1.1.1.2     lukem 	rc = op2.o_bd->bd_info->bi_entry_get_rw( &op2, &mndn, oc, at, rw, ep );
    913  1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS && *ep != NULL ) {
    914  1.1.1.2     lukem 		/* we assume be_entry_release() needs to be called */
    915  1.1.1.2     lukem 		rs.sr_flags = REP_ENTRY_MUSTRELEASE;
    916  1.1.1.2     lukem 		rs.sr_entry = *ep;
    917  1.1.1.2     lukem 
    918  1.1.1.2     lukem 		/* duplicate & release */
    919  1.1.1.2     lukem 		op2.o_bd->bd_info = (BackendInfo *)on;
    920  1.1.1.2     lukem 		rc = rwm_send_entry( &op2, &rs );
    921  1.1.1.4      tron 		RS_ASSERT( rs.sr_flags & REP_ENTRY_MUSTFLUSH );
    922  1.1.1.2     lukem 		if ( rc == SLAP_CB_CONTINUE ) {
    923  1.1.1.2     lukem 			*ep = rs.sr_entry;
    924  1.1.1.2     lukem 			rc = LDAP_SUCCESS;
    925  1.1.1.4      tron 		} else {
    926  1.1.1.4      tron 			assert( rc != LDAP_SUCCESS && rs.sr_entry == *ep );
    927  1.1.1.4      tron 			*ep = NULL;
    928  1.1.1.4      tron 			op2.o_bd->bd_info = (BackendInfo *)on->on_info;
    929  1.1.1.4      tron 			be_entry_release_r( &op2, rs.sr_entry );
    930  1.1.1.4      tron 			op2.o_bd->bd_info = (BackendInfo *)on;
    931  1.1.1.2     lukem 		}
    932  1.1.1.2     lukem 	}
    933  1.1.1.2     lukem 
    934  1.1.1.2     lukem 	if ( !BER_BVISNULL( &ros.r_ndn) && ros.r_ndn.bv_val != ndn->bv_val ) {
    935  1.1.1.2     lukem 		op->o_tmpfree( ros.r_ndn.bv_val, op->o_tmpmemctx );
    936  1.1.1.2     lukem 	}
    937  1.1.1.2     lukem 
    938  1.1.1.2     lukem 	return rc;
    939  1.1.1.2     lukem }
    940  1.1.1.2     lukem 
    941      1.1     lukem static int
    942      1.1     lukem rwm_op_search( Operation *op, SlapReply *rs )
    943      1.1     lukem {
    944      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    945      1.1     lukem 	struct ldaprwmap	*rwmap =
    946      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    947      1.1     lukem 
    948      1.1     lukem 	int			rc;
    949      1.1     lukem 	dncookie		dc;
    950      1.1     lukem 
    951      1.1     lukem 	struct berval		fstr = BER_BVNULL;
    952      1.1     lukem 	Filter			*f = NULL;
    953      1.1     lukem 
    954      1.1     lukem 	AttributeName		*an = NULL;
    955      1.1     lukem 
    956      1.1     lukem 	char			*text = NULL;
    957      1.1     lukem 
    958  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    959      1.1     lukem 
    960      1.1     lukem 	rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
    961      1.1     lukem 		"searchFilter", op->ors_filterstr.bv_val );
    962      1.1     lukem 	if ( rc == LDAP_SUCCESS )
    963      1.1     lukem 		rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
    964      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    965      1.1     lukem 		text = "searchDN massage error";
    966      1.1     lukem 		goto error_return;
    967      1.1     lukem 	}
    968      1.1     lukem 
    969      1.1     lukem 	/*
    970      1.1     lukem 	 * Rewrite the dn if needed
    971      1.1     lukem 	 */
    972      1.1     lukem 	dc.rwmap = rwmap;
    973      1.1     lukem 	dc.conn = op->o_conn;
    974      1.1     lukem 	dc.rs = rs;
    975      1.1     lukem 	dc.ctx = "searchFilterAttrDN";
    976      1.1     lukem 
    977      1.1     lukem 	rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
    978      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    979      1.1     lukem 		text = "searchFilter/searchFilterAttrDN massage error";
    980      1.1     lukem 		goto error_return;
    981      1.1     lukem 	}
    982      1.1     lukem 
    983      1.1     lukem 	f = str2filter_x( op, fstr.bv_val );
    984      1.1     lukem 
    985      1.1     lukem 	if ( f == NULL ) {
    986      1.1     lukem 		text = "massaged filter parse error";
    987      1.1     lukem 		goto error_return;
    988      1.1     lukem 	}
    989      1.1     lukem 
    990      1.1     lukem 	op->ors_filter = f;
    991      1.1     lukem 	op->ors_filterstr = fstr;
    992      1.1     lukem 
    993  1.1.1.3      adam 	rc = rwm_map_attrnames( op, &rwmap->rwm_at, &rwmap->rwm_oc,
    994      1.1     lukem 			op->ors_attrs, &an, RWM_MAP );
    995      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    996      1.1     lukem 		text = "attribute list mapping error";
    997      1.1     lukem 		goto error_return;
    998      1.1     lukem 	}
    999      1.1     lukem 
   1000      1.1     lukem 	op->ors_attrs = an;
   1001      1.1     lukem 	/* store the mapped Attributes for later usage, in
   1002      1.1     lukem 	 * the case that other overlays change op->ors_attrs */
   1003      1.1     lukem 	roc->ros.mapped_attrs = an;
   1004      1.1     lukem 	roc->cb.sc_response = rwm_swap_attrs;
   1005      1.1     lukem 
   1006      1.1     lukem 	op->o_callback = &roc->cb;
   1007      1.1     lukem 
   1008      1.1     lukem 	return SLAP_CB_CONTINUE;
   1009      1.1     lukem 
   1010      1.1     lukem error_return:;
   1011      1.1     lukem 	if ( an != NULL ) {
   1012      1.1     lukem 		ch_free( an );
   1013      1.1     lukem 	}
   1014      1.1     lukem 
   1015      1.1     lukem 	if ( f != NULL ) {
   1016  1.1.1.2     lukem 		filter_free_x( op, f, 1 );
   1017      1.1     lukem 	}
   1018      1.1     lukem 
   1019      1.1     lukem 	if ( !BER_BVISNULL( &fstr ) ) {
   1020  1.1.1.3      adam 		op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
   1021      1.1     lukem 	}
   1022      1.1     lukem 
   1023  1.1.1.2     lukem 	rwm_op_rollback( op, rs, &roc->ros );
   1024      1.1     lukem 	op->oq_search = roc->ros.oq_search;
   1025  1.1.1.2     lukem 	op->o_tmpfree( roc, op->o_tmpmemctx );
   1026      1.1     lukem 
   1027      1.1     lukem 	op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1028      1.1     lukem 	send_ldap_error( op, rs, rc, text );
   1029      1.1     lukem 
   1030      1.1     lukem 	return -1;
   1031      1.1     lukem 
   1032      1.1     lukem }
   1033      1.1     lukem 
   1034      1.1     lukem static int
   1035      1.1     lukem rwm_exop_passwd( Operation *op, SlapReply *rs )
   1036      1.1     lukem {
   1037      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1038      1.1     lukem 	int			rc;
   1039      1.1     lukem 	rwm_op_cb *roc;
   1040      1.1     lukem 
   1041      1.1     lukem 	struct berval	id = BER_BVNULL,
   1042      1.1     lukem 			pwold = BER_BVNULL,
   1043      1.1     lukem 			pwnew = BER_BVNULL;
   1044      1.1     lukem 	BerElement *ber = NULL;
   1045      1.1     lukem 
   1046      1.1     lukem 	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
   1047      1.1     lukem 		return LDAP_SUCCESS;
   1048      1.1     lukem 	}
   1049      1.1     lukem 
   1050      1.1     lukem 	if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
   1051      1.1     lukem 		rs->sr_err = LDAP_OTHER;
   1052      1.1     lukem 		return rs->sr_err;
   1053      1.1     lukem 	}
   1054      1.1     lukem 
   1055      1.1     lukem 	rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
   1056      1.1     lukem 		&pwold, &pwnew, &rs->sr_text );
   1057      1.1     lukem 	if ( rs->sr_err != LDAP_SUCCESS ) {
   1058      1.1     lukem 		return rs->sr_err;
   1059      1.1     lukem 	}
   1060      1.1     lukem 
   1061      1.1     lukem 	if ( !BER_BVISNULL( &id ) ) {
   1062      1.1     lukem 		char idNul = id.bv_val[id.bv_len];
   1063      1.1     lukem 		id.bv_val[id.bv_len] = '\0';
   1064      1.1     lukem 		rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
   1065      1.1     lukem 				&op->o_req_ndn, op->o_tmpmemctx );
   1066      1.1     lukem 		id.bv_val[id.bv_len] = idNul;
   1067      1.1     lukem 		if ( rs->sr_err != LDAP_SUCCESS ) {
   1068      1.1     lukem 			rs->sr_text = "Invalid DN";
   1069      1.1     lukem 			return rs->sr_err;
   1070      1.1     lukem 		}
   1071      1.1     lukem 
   1072      1.1     lukem 	} else {
   1073      1.1     lukem 		ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
   1074      1.1     lukem 		ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
   1075      1.1     lukem 	}
   1076      1.1     lukem 
   1077  1.1.1.4      tron 	roc = rwm_callback_get( op );
   1078      1.1     lukem 
   1079      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
   1080      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1081      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1082      1.1     lukem 		send_ldap_error( op, rs, rc, "extendedDN massage error" );
   1083      1.1     lukem 		return -1;
   1084      1.1     lukem 	}
   1085      1.1     lukem 
   1086      1.1     lukem 	ber = ber_alloc_t( LBER_USE_DER );
   1087      1.1     lukem 	if ( !ber ) {
   1088      1.1     lukem 		rs->sr_err = LDAP_OTHER;
   1089      1.1     lukem 		rs->sr_text = "No memory";
   1090      1.1     lukem 		return rs->sr_err;
   1091      1.1     lukem 	}
   1092      1.1     lukem 	ber_printf( ber, "{" );
   1093      1.1     lukem 	if ( !BER_BVISNULL( &id )) {
   1094      1.1     lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
   1095      1.1     lukem 			&op->o_req_dn );
   1096      1.1     lukem 	}
   1097      1.1     lukem 	if ( !BER_BVISNULL( &pwold )) {
   1098      1.1     lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
   1099      1.1     lukem 	}
   1100      1.1     lukem 	if ( !BER_BVISNULL( &pwnew )) {
   1101      1.1     lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
   1102      1.1     lukem 	}
   1103      1.1     lukem 	ber_printf( ber, "N}" );
   1104      1.1     lukem 	ber_flatten( ber, &op->ore_reqdata );
   1105      1.1     lukem 	ber_free( ber, 1 );
   1106      1.1     lukem 
   1107      1.1     lukem 	op->o_callback = &roc->cb;
   1108      1.1     lukem 
   1109      1.1     lukem 	return SLAP_CB_CONTINUE;
   1110      1.1     lukem }
   1111      1.1     lukem 
   1112      1.1     lukem static struct exop {
   1113      1.1     lukem 	struct berval	oid;
   1114      1.1     lukem 	BI_op_extended	*extended;
   1115      1.1     lukem } exop_table[] = {
   1116      1.1     lukem 	{ BER_BVC(LDAP_EXOP_MODIFY_PASSWD),	rwm_exop_passwd },
   1117      1.1     lukem 	{ BER_BVNULL, NULL }
   1118      1.1     lukem };
   1119      1.1     lukem 
   1120      1.1     lukem static int
   1121      1.1     lukem rwm_extended( Operation *op, SlapReply *rs )
   1122      1.1     lukem {
   1123      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1124      1.1     lukem 	int			rc;
   1125      1.1     lukem 	rwm_op_cb *roc;
   1126      1.1     lukem 
   1127      1.1     lukem 	int	i;
   1128      1.1     lukem 
   1129      1.1     lukem 	for ( i = 0; exop_table[i].extended != NULL; i++ ) {
   1130      1.1     lukem 		if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
   1131      1.1     lukem 		{
   1132      1.1     lukem 			rc = exop_table[i].extended( op, rs );
   1133      1.1     lukem 			switch ( rc ) {
   1134      1.1     lukem 			case LDAP_SUCCESS:
   1135      1.1     lukem 				break;
   1136      1.1     lukem 
   1137      1.1     lukem 			case SLAP_CB_CONTINUE:
   1138      1.1     lukem 			case SLAPD_ABANDON:
   1139      1.1     lukem 				return rc;
   1140      1.1     lukem 
   1141      1.1     lukem 			default:
   1142      1.1     lukem 				send_ldap_result( op, rs );
   1143      1.1     lukem 				return rc;
   1144      1.1     lukem 			}
   1145      1.1     lukem 			break;
   1146      1.1     lukem 		}
   1147      1.1     lukem 	}
   1148      1.1     lukem 
   1149  1.1.1.4      tron 	roc = rwm_callback_get( op );
   1150      1.1     lukem 
   1151      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
   1152      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1153      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1154      1.1     lukem 		send_ldap_error( op, rs, rc, "extendedDN massage error" );
   1155      1.1     lukem 		return -1;
   1156      1.1     lukem 	}
   1157      1.1     lukem 
   1158      1.1     lukem 	/* TODO: rewrite/map extended data ? ... */
   1159      1.1     lukem 	op->o_callback = &roc->cb;
   1160      1.1     lukem 
   1161      1.1     lukem 	return SLAP_CB_CONTINUE;
   1162      1.1     lukem }
   1163      1.1     lukem 
   1164  1.1.1.4      tron static void
   1165      1.1     lukem rwm_matched( Operation *op, SlapReply *rs )
   1166      1.1     lukem {
   1167      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1168      1.1     lukem 	struct ldaprwmap	*rwmap =
   1169      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1170      1.1     lukem 
   1171      1.1     lukem 	struct berval		dn, mdn;
   1172      1.1     lukem 	dncookie		dc;
   1173      1.1     lukem 	int			rc;
   1174      1.1     lukem 
   1175      1.1     lukem 	if ( rs->sr_matched == NULL ) {
   1176  1.1.1.4      tron 		return;
   1177      1.1     lukem 	}
   1178      1.1     lukem 
   1179      1.1     lukem 	dc.rwmap = rwmap;
   1180      1.1     lukem 	dc.conn = op->o_conn;
   1181      1.1     lukem 	dc.rs = rs;
   1182      1.1     lukem 	dc.ctx = "matchedDN";
   1183      1.1     lukem 	ber_str2bv( rs->sr_matched, 0, 0, &dn );
   1184      1.1     lukem 	mdn = dn;
   1185      1.1     lukem 	rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
   1186      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1187      1.1     lukem 		rs->sr_err = rc;
   1188      1.1     lukem 		rs->sr_text = "Rewrite error";
   1189      1.1     lukem 
   1190  1.1.1.4      tron 	} else if ( mdn.bv_val != dn.bv_val ) {
   1191      1.1     lukem 		if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
   1192      1.1     lukem 			ch_free( (void *)rs->sr_matched );
   1193      1.1     lukem 
   1194      1.1     lukem 		} else {
   1195      1.1     lukem 			rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
   1196      1.1     lukem 		}
   1197      1.1     lukem 		rs->sr_matched = mdn.bv_val;
   1198      1.1     lukem 	}
   1199      1.1     lukem }
   1200      1.1     lukem 
   1201      1.1     lukem static int
   1202      1.1     lukem rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
   1203      1.1     lukem {
   1204      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1205      1.1     lukem 	struct ldaprwmap	*rwmap =
   1206      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1207      1.1     lukem 
   1208      1.1     lukem 	dncookie		dc;
   1209      1.1     lukem 	int			rc;
   1210      1.1     lukem 	Attribute		**ap;
   1211      1.1     lukem 	int			isupdate;
   1212      1.1     lukem 	int			check_duplicate_attrs = 0;
   1213      1.1     lukem 
   1214      1.1     lukem 	/*
   1215      1.1     lukem 	 * Rewrite the dn attrs, if needed
   1216      1.1     lukem 	 */
   1217      1.1     lukem 	dc.rwmap = rwmap;
   1218      1.1     lukem 	dc.conn = op->o_conn;
   1219      1.1     lukem 	dc.rs = NULL;
   1220      1.1     lukem 
   1221      1.1     lukem 	/* FIXME: the entries are in the remote mapping form;
   1222      1.1     lukem 	 * so we need to select those attributes we are willing
   1223      1.1     lukem 	 * to return, and remap them accordingly */
   1224      1.1     lukem 
   1225      1.1     lukem 	/* FIXME: in principle, one could map an attribute
   1226      1.1     lukem 	 * on top of another, which already exists.
   1227      1.1     lukem 	 * As such, in the end there might exist more than
   1228      1.1     lukem 	 * one instance of an attribute.
   1229      1.1     lukem 	 * We should at least check if this occurs, and issue
   1230      1.1     lukem 	 * an error (because multiple instances of attrs in
   1231      1.1     lukem 	 * response are not valid), or merge the values (what
   1232      1.1     lukem 	 * about duplicate values?) */
   1233      1.1     lukem 	isupdate = be_shadow_update( op );
   1234      1.1     lukem 	for ( ap = a_first; *ap; ) {
   1235      1.1     lukem 		struct ldapmapping	*mapping = NULL;
   1236      1.1     lukem 		int			drop_missing;
   1237      1.1     lukem 		int			last = -1;
   1238      1.1     lukem 		Attribute		*a;
   1239      1.1     lukem 
   1240  1.1.1.2     lukem 		if ( ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS ) &&
   1241  1.1.1.2     lukem 				op->ors_attrs != NULL &&
   1242  1.1.1.2     lukem 				!SLAP_USERATTRS( rs->sr_attr_flags ) &&
   1243  1.1.1.2     lukem 				!ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
   1244      1.1     lukem 		{
   1245  1.1.1.2     lukem 			goto cleanup_attr;
   1246  1.1.1.2     lukem 		}
   1247      1.1     lukem 
   1248  1.1.1.2     lukem 		drop_missing = rwm_mapping( &rwmap->rwm_at,
   1249  1.1.1.2     lukem 				&(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
   1250  1.1.1.2     lukem 		if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
   1251  1.1.1.2     lukem 		{
   1252  1.1.1.2     lukem 			goto cleanup_attr;
   1253  1.1.1.2     lukem 		}
   1254  1.1.1.2     lukem 		if ( mapping != NULL ) {
   1255  1.1.1.2     lukem 			assert( mapping->m_dst_ad != NULL );
   1256      1.1     lukem 
   1257  1.1.1.2     lukem 			/* try to normalize mapped Attributes if the original
   1258  1.1.1.2     lukem 			 * AttributeType was not normalized */
   1259  1.1.1.2     lukem 			if ( (!(*ap)->a_desc->ad_type->sat_equality ||
   1260  1.1.1.2     lukem 				!(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
   1261  1.1.1.2     lukem 				mapping->m_dst_ad->ad_type->sat_equality &&
   1262  1.1.1.2     lukem 				mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
   1263  1.1.1.2     lukem 			{
   1264  1.1.1.2     lukem 				if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS))
   1265      1.1     lukem 				{
   1266      1.1     lukem 					int i = 0;
   1267      1.1     lukem 
   1268      1.1     lukem 					last = (*ap)->a_numvals;
   1269      1.1     lukem 					if ( last )
   1270      1.1     lukem 					{
   1271      1.1     lukem 						(*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
   1272      1.1     lukem 
   1273      1.1     lukem 						for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
   1274      1.1     lukem 							int		rc;
   1275      1.1     lukem 							/*
   1276      1.1     lukem 							 * check that each value is valid per syntax
   1277      1.1     lukem 							 * and pretty if appropriate
   1278      1.1     lukem 							 */
   1279      1.1     lukem 							rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
   1280      1.1     lukem 								SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
   1281      1.1     lukem 								mapping->m_dst_ad->ad_type->sat_syntax,
   1282      1.1     lukem 								mapping->m_dst_ad->ad_type->sat_equality,
   1283      1.1     lukem 								&(*ap)->a_vals[i], &(*ap)->a_nvals[i],
   1284      1.1     lukem 								NULL );
   1285      1.1     lukem 
   1286      1.1     lukem 							if ( rc != LDAP_SUCCESS ) {
   1287  1.1.1.4      tron 								/* FIXME: this is wrong, putting a non-normalized value
   1288  1.1.1.4      tron 								 * into nvals. But when a proxy sends us bogus data,
   1289  1.1.1.4      tron 								 * we still need to give it to the client, even if it
   1290  1.1.1.4      tron 								 * violates the syntax. I.e., we don't want to silently
   1291  1.1.1.4      tron 								 * drop things and trigger an apparent data loss.
   1292  1.1.1.4      tron 								 */
   1293  1.1.1.4      tron 								ber_dupbv( &(*ap)->a_nvals[i], &(*ap)->a_vals[i] );
   1294      1.1     lukem 							}
   1295      1.1     lukem 						}
   1296      1.1     lukem 						BER_BVZERO( &(*ap)->a_nvals[i] );
   1297      1.1     lukem 					}
   1298  1.1.1.2     lukem 
   1299  1.1.1.2     lukem 				} else {
   1300  1.1.1.2     lukem 					assert( (*ap)->a_nvals == (*ap)->a_vals );
   1301  1.1.1.2     lukem 					(*ap)->a_nvals = NULL;
   1302  1.1.1.2     lukem 					ber_bvarray_dup_x( &(*ap)->a_nvals, (*ap)->a_vals, NULL );
   1303      1.1     lukem 				}
   1304  1.1.1.2     lukem 			}
   1305      1.1     lukem 
   1306  1.1.1.2     lukem 			/* rewrite the attribute description */
   1307  1.1.1.2     lukem 			(*ap)->a_desc = mapping->m_dst_ad;
   1308      1.1     lukem 
   1309  1.1.1.2     lukem 			/* will need to check for duplicate attrs */
   1310  1.1.1.2     lukem 			check_duplicate_attrs++;
   1311      1.1     lukem 		}
   1312      1.1     lukem 
   1313      1.1     lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
   1314      1.1     lukem 			if ( stripEntryDN ) {
   1315      1.1     lukem 				/* will be generated by frontend */
   1316      1.1     lukem 				goto cleanup_attr;
   1317      1.1     lukem 			}
   1318      1.1     lukem 
   1319      1.1     lukem 		} else if ( !isupdate
   1320      1.1     lukem 			&& !get_relax( op )
   1321      1.1     lukem 			&& (*ap)->a_desc->ad_type->sat_no_user_mod
   1322      1.1     lukem 			&& (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
   1323      1.1     lukem 		{
   1324      1.1     lukem 			goto next_attr;
   1325      1.1     lukem 		}
   1326      1.1     lukem 
   1327      1.1     lukem 		if ( last == -1 ) { /* not yet counted */
   1328      1.1     lukem 			last = (*ap)->a_numvals;
   1329      1.1     lukem 		}
   1330      1.1     lukem 
   1331      1.1     lukem 		if ( last == 0 ) {
   1332      1.1     lukem 			/* empty? leave it in place because of attrsonly and vlv */
   1333      1.1     lukem 			goto next_attr;
   1334      1.1     lukem 		}
   1335      1.1     lukem 		last--;
   1336      1.1     lukem 
   1337      1.1     lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
   1338      1.1     lukem 				|| (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
   1339      1.1     lukem 		{
   1340      1.1     lukem 			struct berval	*bv;
   1341      1.1     lukem 
   1342      1.1     lukem 			for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
   1343      1.1     lukem 				struct berval	mapped;
   1344      1.1     lukem 
   1345      1.1     lukem 				rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
   1346      1.1     lukem 				if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
   1347      1.1     lukem remove_oc:;
   1348      1.1     lukem 					ch_free( bv[0].bv_val );
   1349      1.1     lukem 					BER_BVZERO( &bv[0] );
   1350      1.1     lukem 					if ( &(*ap)->a_vals[last] > &bv[0] ) {
   1351      1.1     lukem 						bv[0] = (*ap)->a_vals[last];
   1352      1.1     lukem 						BER_BVZERO( &(*ap)->a_vals[last] );
   1353      1.1     lukem 					}
   1354      1.1     lukem 					last--;
   1355      1.1     lukem 					bv--;
   1356      1.1     lukem 
   1357  1.1.1.2     lukem 				} else if ( mapped.bv_val != bv[0].bv_val
   1358  1.1.1.2     lukem 					&& ber_bvstrcasecmp( &mapped, &bv[0] ) != 0 )
   1359  1.1.1.2     lukem 				{
   1360      1.1     lukem 					int	i;
   1361      1.1     lukem 
   1362      1.1     lukem 					for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
   1363      1.1     lukem 						if ( &(*ap)->a_vals[ i ] == bv ) {
   1364      1.1     lukem 							continue;
   1365      1.1     lukem 						}
   1366      1.1     lukem 
   1367      1.1     lukem 						if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
   1368      1.1     lukem 							break;
   1369      1.1     lukem 						}
   1370      1.1     lukem 					}
   1371      1.1     lukem 
   1372      1.1     lukem 					if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
   1373      1.1     lukem 						goto remove_oc;
   1374      1.1     lukem 					}
   1375      1.1     lukem 
   1376      1.1     lukem 					/*
   1377      1.1     lukem 					 * FIXME: after LBER_FREEing
   1378      1.1     lukem 					 * the value is replaced by
   1379      1.1     lukem 					 * ch_alloc'ed memory
   1380      1.1     lukem 					 */
   1381      1.1     lukem 					ber_bvreplace( &bv[0], &mapped );
   1382      1.1     lukem 
   1383      1.1     lukem 					/* FIXME: will need to check
   1384      1.1     lukem 					 * if the structuralObjectClass
   1385      1.1     lukem 					 * changed */
   1386      1.1     lukem 				}
   1387      1.1     lukem 			}
   1388      1.1     lukem 
   1389      1.1     lukem 		/*
   1390      1.1     lukem 		 * It is necessary to try to rewrite attributes with
   1391      1.1     lukem 		 * dn syntax because they might be used in ACLs as
   1392      1.1     lukem 		 * members of groups; since ACLs are applied to the
   1393      1.1     lukem 		 * rewritten stuff, no dn-based subject clause could
   1394      1.1     lukem 		 * be used at the ldap backend side (see
   1395      1.1     lukem 		 * http://www.OpenLDAP.org/faq/data/cache/452.html)
   1396      1.1     lukem 		 * The problem can be overcome by moving the dn-based
   1397      1.1     lukem 		 * ACLs to the target directory server, and letting
   1398      1.1     lukem 		 * everything pass thru the ldap backend. */
   1399      1.1     lukem 		/* FIXME: handle distinguishedName-like syntaxes, like
   1400      1.1     lukem 		 * nameAndOptionalUID */
   1401      1.1     lukem 		} else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
   1402      1.1     lukem 				|| ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
   1403      1.1     lukem 		{
   1404      1.1     lukem 			dc.ctx = "searchAttrDN";
   1405  1.1.1.2     lukem 			rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals, (*ap)->a_nvals );
   1406      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
   1407      1.1     lukem 				goto cleanup_attr;
   1408      1.1     lukem 			}
   1409      1.1     lukem 
   1410      1.1     lukem 		} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
   1411      1.1     lukem 			dc.ctx = "searchAttrDN";
   1412      1.1     lukem 			rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
   1413      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
   1414      1.1     lukem 				goto cleanup_attr;
   1415      1.1     lukem 			}
   1416      1.1     lukem 		}
   1417      1.1     lukem 
   1418      1.1     lukem 
   1419      1.1     lukem next_attr:;
   1420      1.1     lukem 		ap = &(*ap)->a_next;
   1421      1.1     lukem 		continue;
   1422      1.1     lukem 
   1423      1.1     lukem cleanup_attr:;
   1424      1.1     lukem 		a = *ap;
   1425      1.1     lukem 		*ap = (*ap)->a_next;
   1426      1.1     lukem 
   1427      1.1     lukem 		attr_free( a );
   1428      1.1     lukem 	}
   1429      1.1     lukem 
   1430      1.1     lukem 	/* only check if some mapping occurred */
   1431      1.1     lukem 	if ( check_duplicate_attrs ) {
   1432      1.1     lukem 		for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
   1433      1.1     lukem 			Attribute	**tap;
   1434      1.1     lukem 
   1435      1.1     lukem 			for ( tap = &(*ap)->a_next; *tap != NULL; ) {
   1436      1.1     lukem 				if ( (*tap)->a_desc == (*ap)->a_desc ) {
   1437      1.1     lukem 					Entry		e = { 0 };
   1438      1.1     lukem 					Modification	mod = { 0 };
   1439      1.1     lukem 					const char	*text = NULL;
   1440      1.1     lukem 					char		textbuf[ SLAP_TEXT_BUFLEN ];
   1441      1.1     lukem 					Attribute	*next = (*tap)->a_next;
   1442      1.1     lukem 
   1443      1.1     lukem 					BER_BVSTR( &e.e_name, "" );
   1444      1.1     lukem 					BER_BVSTR( &e.e_nname, "" );
   1445      1.1     lukem 					e.e_attrs = *ap;
   1446      1.1     lukem 					mod.sm_op = LDAP_MOD_ADD;
   1447      1.1     lukem 					mod.sm_desc = (*ap)->a_desc;
   1448      1.1     lukem 					mod.sm_type = mod.sm_desc->ad_cname;
   1449      1.1     lukem 					mod.sm_numvals = (*tap)->a_numvals;
   1450      1.1     lukem 					mod.sm_values = (*tap)->a_vals;
   1451      1.1     lukem 					if ( (*tap)->a_nvals != (*tap)->a_vals ) {
   1452      1.1     lukem 						mod.sm_nvalues = (*tap)->a_nvals;
   1453      1.1     lukem 					}
   1454      1.1     lukem 
   1455      1.1     lukem 					(void)modify_add_values( &e, &mod,
   1456      1.1     lukem 						/* permissive */ 1,
   1457      1.1     lukem 						&text, textbuf, sizeof( textbuf ) );
   1458      1.1     lukem 
   1459      1.1     lukem 					/* should not insert new attrs! */
   1460      1.1     lukem 					assert( e.e_attrs == *ap );
   1461      1.1     lukem 
   1462      1.1     lukem 					attr_free( *tap );
   1463      1.1     lukem 					*tap = next;
   1464      1.1     lukem 
   1465      1.1     lukem 				} else {
   1466      1.1     lukem 					tap = &(*tap)->a_next;
   1467      1.1     lukem 				}
   1468      1.1     lukem 			}
   1469      1.1     lukem 		}
   1470      1.1     lukem 	}
   1471      1.1     lukem 
   1472      1.1     lukem 	return 0;
   1473      1.1     lukem }
   1474      1.1     lukem 
   1475  1.1.1.4      tron /* Should return SLAP_CB_CONTINUE or failure, never LDAP_SUCCESS. */
   1476      1.1     lukem static int
   1477      1.1     lukem rwm_send_entry( Operation *op, SlapReply *rs )
   1478      1.1     lukem {
   1479      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1480      1.1     lukem 	struct ldaprwmap	*rwmap =
   1481      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1482      1.1     lukem 
   1483      1.1     lukem 	Entry			*e = NULL;
   1484      1.1     lukem 	struct berval		dn = BER_BVNULL,
   1485      1.1     lukem 				ndn = BER_BVNULL;
   1486      1.1     lukem 	dncookie		dc;
   1487      1.1     lukem 	int			rc;
   1488      1.1     lukem 
   1489      1.1     lukem 	assert( rs->sr_entry != NULL );
   1490      1.1     lukem 
   1491      1.1     lukem 	/*
   1492      1.1     lukem 	 * Rewrite the dn of the result, if needed
   1493      1.1     lukem 	 */
   1494      1.1     lukem 	dc.rwmap = rwmap;
   1495      1.1     lukem 	dc.conn = op->o_conn;
   1496      1.1     lukem 	dc.rs = NULL;
   1497      1.1     lukem 	dc.ctx = "searchEntryDN";
   1498      1.1     lukem 
   1499      1.1     lukem 	e = rs->sr_entry;
   1500      1.1     lukem 	if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
   1501      1.1     lukem 		/* FIXME: all we need to duplicate are:
   1502      1.1     lukem 		 * - dn
   1503      1.1     lukem 		 * - ndn
   1504      1.1     lukem 		 * - attributes that are requested
   1505      1.1     lukem 		 * - no values if attrsonly is set
   1506      1.1     lukem 		 */
   1507      1.1     lukem 		e = entry_dup( e );
   1508      1.1     lukem 		if ( e == NULL ) {
   1509      1.1     lukem 			rc = LDAP_NO_MEMORY;
   1510      1.1     lukem 			goto fail;
   1511      1.1     lukem 		}
   1512  1.1.1.4      tron 	} else if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
   1513  1.1.1.4      tron 		/* ITS#6423: REP_ENTRY_MUSTRELEASE incompatible
   1514  1.1.1.4      tron 		 * with REP_ENTRY_MODIFIABLE */
   1515  1.1.1.4      tron 		RS_ASSERT( 0 );
   1516  1.1.1.4      tron 		rc = 1;
   1517  1.1.1.4      tron 		goto fail;
   1518      1.1     lukem 	}
   1519      1.1     lukem 
   1520      1.1     lukem 	/*
   1521      1.1     lukem 	 * Note: this may fail if the target host(s) schema differs
   1522      1.1     lukem 	 * from the one known to the meta, and a DN with unknown
   1523      1.1     lukem 	 * attributes is returned.
   1524      1.1     lukem 	 */
   1525      1.1     lukem 	dn = e->e_name;
   1526      1.1     lukem 	ndn = e->e_nname;
   1527      1.1     lukem 	rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
   1528      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1529      1.1     lukem 		rc = 1;
   1530      1.1     lukem 		goto fail;
   1531      1.1     lukem 	}
   1532      1.1     lukem 
   1533      1.1     lukem 	if ( e->e_name.bv_val != dn.bv_val ) {
   1534      1.1     lukem 		ch_free( e->e_name.bv_val );
   1535      1.1     lukem 		ch_free( e->e_nname.bv_val );
   1536      1.1     lukem 
   1537      1.1     lukem 		e->e_name = dn;
   1538      1.1     lukem 		e->e_nname = ndn;
   1539      1.1     lukem 	}
   1540      1.1     lukem 
   1541      1.1     lukem 	/* TODO: map entry attribute types, objectclasses
   1542      1.1     lukem 	 * and dn-valued attribute values */
   1543      1.1     lukem 
   1544      1.1     lukem 	/* FIXME: the entries are in the remote mapping form;
   1545      1.1     lukem 	 * so we need to select those attributes we are willing
   1546      1.1     lukem 	 * to return, and remap them accordingly */
   1547      1.1     lukem 	(void)rwm_attrs( op, rs, &e->e_attrs, 1 );
   1548      1.1     lukem 
   1549  1.1.1.4      tron 	if ( e != rs->sr_entry ) {
   1550  1.1.1.4      tron 		/* Reimplementing rs_replace_entry(), I suppose to
   1551  1.1.1.4      tron 		 * bypass our own dubious rwm_entry_release_rw() */
   1552  1.1.1.4      tron 		if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
   1553  1.1.1.4      tron 			rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
   1554  1.1.1.4      tron 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1555  1.1.1.4      tron 			be_entry_release_r( op, rs->sr_entry );
   1556  1.1.1.4      tron 			op->o_bd->bd_info = (BackendInfo *)on;
   1557  1.1.1.4      tron 		} else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
   1558  1.1.1.4      tron 			entry_free( rs->sr_entry );
   1559  1.1.1.3      adam 		}
   1560  1.1.1.4      tron 		rs->sr_entry = e;
   1561  1.1.1.4      tron 		rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
   1562      1.1     lukem 	}
   1563      1.1     lukem 
   1564      1.1     lukem 	return SLAP_CB_CONTINUE;
   1565      1.1     lukem 
   1566      1.1     lukem fail:;
   1567      1.1     lukem 	if ( e != NULL && e != rs->sr_entry ) {
   1568      1.1     lukem 		if ( e->e_name.bv_val == dn.bv_val ) {
   1569      1.1     lukem 			BER_BVZERO( &e->e_name );
   1570      1.1     lukem 		}
   1571      1.1     lukem 
   1572      1.1     lukem 		if ( e->e_nname.bv_val == ndn.bv_val ) {
   1573      1.1     lukem 			BER_BVZERO( &e->e_nname );
   1574      1.1     lukem 		}
   1575      1.1     lukem 
   1576      1.1     lukem 		entry_free( e );
   1577      1.1     lukem 	}
   1578      1.1     lukem 
   1579      1.1     lukem 	if ( !BER_BVISNULL( &dn ) ) {
   1580      1.1     lukem 		ch_free( dn.bv_val );
   1581      1.1     lukem 	}
   1582      1.1     lukem 
   1583      1.1     lukem 	if ( !BER_BVISNULL( &ndn ) ) {
   1584      1.1     lukem 		ch_free( ndn.bv_val );
   1585      1.1     lukem 	}
   1586      1.1     lukem 
   1587      1.1     lukem 	return rc;
   1588      1.1     lukem }
   1589      1.1     lukem 
   1590      1.1     lukem static int
   1591      1.1     lukem rwm_operational( Operation *op, SlapReply *rs )
   1592      1.1     lukem {
   1593      1.1     lukem 	/* FIXME: the entries are in the remote mapping form;
   1594      1.1     lukem 	 * so we need to select those attributes we are willing
   1595      1.1     lukem 	 * to return, and remap them accordingly */
   1596      1.1     lukem 	if ( rs->sr_operational_attrs ) {
   1597      1.1     lukem 		rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
   1598      1.1     lukem 	}
   1599      1.1     lukem 
   1600      1.1     lukem 	return SLAP_CB_CONTINUE;
   1601      1.1     lukem }
   1602      1.1     lukem 
   1603      1.1     lukem #if 0
   1604      1.1     lukem /* don't use this; it cannot be reverted, and leaves op->o_req_dn
   1605      1.1     lukem  * rewritten for subsequent operations; fine for plain suffixmassage,
   1606      1.1     lukem  * but destroys everything else */
   1607      1.1     lukem static int
   1608      1.1     lukem rwm_chk_referrals( Operation *op, SlapReply *rs )
   1609      1.1     lukem {
   1610      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1611      1.1     lukem 	int			rc;
   1612      1.1     lukem 
   1613      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
   1614      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1615      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1616      1.1     lukem 		send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
   1617      1.1     lukem 		return -1;
   1618      1.1     lukem 	}
   1619      1.1     lukem 
   1620      1.1     lukem 	return SLAP_CB_CONTINUE;
   1621      1.1     lukem }
   1622      1.1     lukem #endif
   1623      1.1     lukem 
   1624      1.1     lukem static int
   1625      1.1     lukem rwm_rw_config(
   1626      1.1     lukem 	BackendDB	*be,
   1627      1.1     lukem 	const char	*fname,
   1628      1.1     lukem 	int		lineno,
   1629      1.1     lukem 	int		argc,
   1630      1.1     lukem 	char		**argv )
   1631      1.1     lukem {
   1632      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1633      1.1     lukem 	struct ldaprwmap	*rwmap =
   1634      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1635      1.1     lukem 
   1636      1.1     lukem 	return rewrite_parse( rwmap->rwm_rw,
   1637      1.1     lukem 				fname, lineno, argc, argv );
   1638      1.1     lukem 
   1639      1.1     lukem 	return 0;
   1640      1.1     lukem }
   1641      1.1     lukem 
   1642      1.1     lukem static int
   1643      1.1     lukem rwm_suffixmassage_config(
   1644      1.1     lukem 	BackendDB	*be,
   1645      1.1     lukem 	const char	*fname,
   1646      1.1     lukem 	int		lineno,
   1647      1.1     lukem 	int		argc,
   1648      1.1     lukem 	char		**argv )
   1649      1.1     lukem {
   1650      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1651      1.1     lukem 	struct ldaprwmap	*rwmap =
   1652      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1653      1.1     lukem 
   1654      1.1     lukem 	struct berval		bvnc, nvnc, pvnc, brnc, nrnc, prnc;
   1655      1.1     lukem 	int			massaged;
   1656      1.1     lukem 	int			rc;
   1657      1.1     lukem 
   1658      1.1     lukem 	/*
   1659      1.1     lukem 	 * syntax:
   1660      1.1     lukem 	 *
   1661      1.1     lukem 	 * 	suffixmassage [<suffix>] <massaged suffix>
   1662      1.1     lukem 	 *
   1663      1.1     lukem 	 * the [<suffix>] field must be defined as a valid suffix
   1664      1.1     lukem 	 * for the current database;
   1665      1.1     lukem 	 * the <massaged suffix> shouldn't have already been
   1666      1.1     lukem 	 * defined as a valid suffix for the current server
   1667      1.1     lukem 	 */
   1668      1.1     lukem 	if ( argc == 2 ) {
   1669      1.1     lukem 		if ( be->be_suffix == NULL ) {
   1670  1.1.1.3      adam  			Debug( LDAP_DEBUG_ANY, "%s: line %d: "
   1671      1.1     lukem 				       " \"suffixMassage [<suffix>]"
   1672      1.1     lukem 				       " <massaged suffix>\" without "
   1673      1.1     lukem 				       "<suffix> part requires database "
   1674      1.1     lukem 				       "suffix be defined first.\n",
   1675  1.1.1.3      adam 				fname, lineno, 0 );
   1676      1.1     lukem 			return 1;
   1677      1.1     lukem 		}
   1678      1.1     lukem 		bvnc = be->be_suffix[ 0 ];
   1679      1.1     lukem 		massaged = 1;
   1680      1.1     lukem 
   1681      1.1     lukem 	} else if ( argc == 3 ) {
   1682      1.1     lukem 		ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
   1683      1.1     lukem 		massaged = 2;
   1684      1.1     lukem 
   1685      1.1     lukem 	} else  {
   1686  1.1.1.3      adam  		Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is"
   1687      1.1     lukem 			       " \"suffixMassage [<suffix>]"
   1688      1.1     lukem 			       " <massaged suffix>\"\n",
   1689  1.1.1.3      adam 			fname, lineno, 0 );
   1690      1.1     lukem 		return 1;
   1691      1.1     lukem 	}
   1692      1.1     lukem 
   1693      1.1     lukem 	if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
   1694  1.1.1.3      adam 		Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
   1695      1.1     lukem 			fname, lineno, bvnc.bv_val );
   1696      1.1     lukem 		return 1;
   1697      1.1     lukem 	}
   1698      1.1     lukem 
   1699      1.1     lukem 	ber_str2bv( argv[ massaged ], 0, 0, &brnc );
   1700      1.1     lukem 	if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
   1701  1.1.1.3      adam 		Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
   1702      1.1     lukem 				fname, lineno, brnc.bv_val );
   1703      1.1     lukem 		free( nvnc.bv_val );
   1704      1.1     lukem 		free( pvnc.bv_val );
   1705      1.1     lukem 		return 1;
   1706      1.1     lukem 	}
   1707      1.1     lukem 
   1708      1.1     lukem 	/*
   1709      1.1     lukem 	 * The suffix massaging is emulated
   1710      1.1     lukem 	 * by means of the rewrite capabilities
   1711      1.1     lukem 	 */
   1712      1.1     lukem  	rc = rwm_suffix_massage_config( rwmap->rwm_rw,
   1713      1.1     lukem 			&pvnc, &nvnc, &prnc, &nrnc );
   1714      1.1     lukem 	free( nvnc.bv_val );
   1715      1.1     lukem 	free( pvnc.bv_val );
   1716      1.1     lukem 	free( nrnc.bv_val );
   1717      1.1     lukem 	free( prnc.bv_val );
   1718      1.1     lukem 
   1719      1.1     lukem 	return rc;
   1720      1.1     lukem }
   1721      1.1     lukem 
   1722      1.1     lukem static int
   1723      1.1     lukem rwm_m_config(
   1724      1.1     lukem 	BackendDB	*be,
   1725      1.1     lukem 	const char	*fname,
   1726      1.1     lukem 	int		lineno,
   1727      1.1     lukem 	int		argc,
   1728      1.1     lukem 	char		**argv )
   1729      1.1     lukem {
   1730      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1731      1.1     lukem 	struct ldaprwmap	*rwmap =
   1732      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1733      1.1     lukem 
   1734      1.1     lukem 	/* objectclass/attribute mapping */
   1735      1.1     lukem 	return rwm_map_config( &rwmap->rwm_oc,
   1736      1.1     lukem 			&rwmap->rwm_at,
   1737      1.1     lukem 			fname, lineno, argc, argv );
   1738      1.1     lukem }
   1739      1.1     lukem 
   1740      1.1     lukem static int
   1741      1.1     lukem rwm_response( Operation *op, SlapReply *rs )
   1742      1.1     lukem {
   1743      1.1     lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
   1744      1.1     lukem 	struct ldaprwmap	*rwmap =
   1745      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1746      1.1     lukem 
   1747      1.1     lukem 	int		rc;
   1748      1.1     lukem 
   1749      1.1     lukem 	if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
   1750      1.1     lukem 		return rwm_send_entry( op, rs );
   1751      1.1     lukem 	}
   1752      1.1     lukem 
   1753      1.1     lukem 	switch( op->o_tag ) {
   1754      1.1     lukem 	case LDAP_REQ_SEARCH:
   1755      1.1     lukem 	case LDAP_REQ_BIND:
   1756      1.1     lukem 	case LDAP_REQ_ADD:
   1757      1.1     lukem 	case LDAP_REQ_DELETE:
   1758      1.1     lukem 	case LDAP_REQ_MODRDN:
   1759      1.1     lukem 	case LDAP_REQ_MODIFY:
   1760      1.1     lukem 	case LDAP_REQ_COMPARE:
   1761      1.1     lukem 	case LDAP_REQ_EXTENDED:
   1762      1.1     lukem 		if ( rs->sr_ref ) {
   1763      1.1     lukem 			dncookie		dc;
   1764      1.1     lukem 
   1765      1.1     lukem 			/*
   1766      1.1     lukem 			 * Rewrite the dn of the referrals, if needed
   1767      1.1     lukem 			 */
   1768      1.1     lukem 			dc.rwmap = rwmap;
   1769      1.1     lukem 			dc.conn = op->o_conn;
   1770      1.1     lukem 			dc.rs = NULL;
   1771      1.1     lukem 			dc.ctx = "referralDN";
   1772      1.1     lukem 			rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
   1773  1.1.1.4      tron 			/* FIXME: impossible, so far */
   1774      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
   1775  1.1.1.4      tron 				rs->sr_err = rc;
   1776      1.1     lukem 				break;
   1777      1.1     lukem 			}
   1778      1.1     lukem 		}
   1779      1.1     lukem 
   1780  1.1.1.4      tron 		rwm_matched( op, rs );
   1781      1.1     lukem 		break;
   1782      1.1     lukem 	}
   1783      1.1     lukem 
   1784  1.1.1.4      tron 	return SLAP_CB_CONTINUE;
   1785      1.1     lukem }
   1786      1.1     lukem 
   1787      1.1     lukem static int
   1788      1.1     lukem rwm_db_config(
   1789      1.1     lukem 	BackendDB	*be,
   1790      1.1     lukem 	const char	*fname,
   1791      1.1     lukem 	int		lineno,
   1792      1.1     lukem 	int		argc,
   1793      1.1     lukem 	char		**argv )
   1794      1.1     lukem {
   1795      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1796      1.1     lukem 	struct ldaprwmap	*rwmap =
   1797      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1798      1.1     lukem 
   1799      1.1     lukem 	int		rc = 0;
   1800      1.1     lukem 	char		*argv0 = NULL;
   1801      1.1     lukem 
   1802      1.1     lukem 	if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
   1803      1.1     lukem 		argv0 = argv[ 0 ];
   1804      1.1     lukem 		argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
   1805      1.1     lukem 	}
   1806      1.1     lukem 
   1807      1.1     lukem 	if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
   1808      1.1     lukem 		rc = rwm_rw_config( be, fname, lineno, argc, argv );
   1809      1.1     lukem 
   1810      1.1     lukem 	} else if ( strcasecmp( argv[0], "map" ) == 0 ) {
   1811      1.1     lukem 		rc = rwm_m_config( be, fname, lineno, argc, argv );
   1812      1.1     lukem 
   1813      1.1     lukem 	} else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
   1814      1.1     lukem 		rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
   1815      1.1     lukem 
   1816      1.1     lukem 	} else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
   1817      1.1     lukem 		if ( argc != 2 ) {
   1818  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1819      1.1     lukem 		"%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
   1820  1.1.1.3      adam 					fname, lineno, 0 );
   1821      1.1     lukem 			return( 1 );
   1822      1.1     lukem 		}
   1823      1.1     lukem 
   1824      1.1     lukem 		if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
   1825      1.1     lukem 			rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
   1826      1.1     lukem 
   1827      1.1     lukem 		} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
   1828      1.1     lukem 			rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
   1829      1.1     lukem 
   1830      1.1     lukem 		/* TODO: not implemented yet */
   1831      1.1     lukem 		} else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
   1832  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1833      1.1     lukem 		"%s: line %d: \"discover\" not supported yet "
   1834      1.1     lukem 		"in \"t-f-support {no|yes|discover}\".\n",
   1835  1.1.1.3      adam 					fname, lineno, 0 );
   1836      1.1     lukem 			return( 1 );
   1837      1.1     lukem #if 0
   1838      1.1     lukem 			rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
   1839      1.1     lukem #endif
   1840      1.1     lukem 
   1841      1.1     lukem 		} else {
   1842  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1843      1.1     lukem 	"%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
   1844      1.1     lukem 				fname, lineno, argv[ 1 ] );
   1845      1.1     lukem 			return 1;
   1846      1.1     lukem 		}
   1847      1.1     lukem 
   1848      1.1     lukem 	} else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) ==  0 ) {
   1849      1.1     lukem 		if ( argc !=2 ) {
   1850  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1851      1.1     lukem 		"%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
   1852  1.1.1.3      adam 					fname, lineno, 0 );
   1853      1.1     lukem 			return( 1 );
   1854      1.1     lukem 		}
   1855      1.1     lukem 
   1856      1.1     lukem 		if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
   1857      1.1     lukem 			rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
   1858      1.1     lukem 
   1859      1.1     lukem 		} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
   1860      1.1     lukem 			rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
   1861      1.1     lukem 		}
   1862      1.1     lukem 
   1863      1.1     lukem 	} else {
   1864      1.1     lukem 		rc = SLAP_CONF_UNKNOWN;
   1865      1.1     lukem 	}
   1866      1.1     lukem 
   1867      1.1     lukem 	if ( argv0 ) {
   1868      1.1     lukem 		argv[ 0 ] = argv0;
   1869      1.1     lukem 	}
   1870      1.1     lukem 
   1871      1.1     lukem 	return rc;
   1872      1.1     lukem }
   1873      1.1     lukem 
   1874      1.1     lukem /*
   1875      1.1     lukem  * dynamic configuration...
   1876      1.1     lukem  */
   1877      1.1     lukem 
   1878      1.1     lukem enum {
   1879      1.1     lukem 	/* rewrite */
   1880      1.1     lukem 	RWM_CF_REWRITE = 1,
   1881      1.1     lukem 
   1882      1.1     lukem 	/* map */
   1883      1.1     lukem 	RWM_CF_MAP,
   1884      1.1     lukem 	RWM_CF_T_F_SUPPORT,
   1885      1.1     lukem 	RWM_CF_NORMALIZE_MAPPED,
   1886  1.1.1.2     lukem 	RWM_CF_DROP_UNREQUESTED,
   1887      1.1     lukem 
   1888      1.1     lukem 	RWM_CF_LAST
   1889      1.1     lukem };
   1890      1.1     lukem 
   1891      1.1     lukem static slap_verbmasks t_f_mode[] = {
   1892  1.1.1.2     lukem 	{ BER_BVC( "true" ),		RWM_F_SUPPORT_T_F },
   1893      1.1     lukem 	{ BER_BVC( "yes" ),		RWM_F_SUPPORT_T_F },
   1894      1.1     lukem 	{ BER_BVC( "discover" ),	RWM_F_SUPPORT_T_F_DISCOVER },
   1895  1.1.1.2     lukem 	{ BER_BVC( "false" ),		RWM_F_NONE },
   1896      1.1     lukem 	{ BER_BVC( "no" ),		RWM_F_NONE },
   1897      1.1     lukem 	{ BER_BVNULL,			0 }
   1898      1.1     lukem };
   1899      1.1     lukem 
   1900      1.1     lukem static ConfigDriver rwm_cf_gen;
   1901      1.1     lukem 
   1902      1.1     lukem static ConfigTable rwmcfg[] = {
   1903      1.1     lukem 	{ "rwm-rewrite", "rewrite",
   1904      1.1     lukem 		2, 0, STRLENOF("rwm-rewrite"),
   1905  1.1.1.2     lukem 		ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
   1906      1.1     lukem 		"( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
   1907      1.1     lukem 			"DESC 'Rewrites strings' "
   1908      1.1     lukem 			"EQUALITY caseIgnoreMatch "
   1909      1.1     lukem 			"SYNTAX OMsDirectoryString "
   1910      1.1     lukem 			"X-ORDERED 'VALUES' )",
   1911      1.1     lukem 		NULL, NULL },
   1912      1.1     lukem 
   1913      1.1     lukem 	{ "rwm-suffixmassage", "[virtual]> <real",
   1914  1.1.1.2     lukem 		2, 3, 0, ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
   1915      1.1     lukem 		NULL, NULL, NULL },
   1916      1.1     lukem 
   1917      1.1     lukem 	{ "rwm-t-f-support", "true|false|discover",
   1918      1.1     lukem 		2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
   1919      1.1     lukem 		"( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
   1920      1.1     lukem 			"DESC 'Absolute filters support' "
   1921      1.1     lukem 			"SYNTAX OMsDirectoryString "
   1922      1.1     lukem 			"SINGLE-VALUE )",
   1923      1.1     lukem 		NULL, NULL },
   1924      1.1     lukem 
   1925      1.1     lukem 	{ "rwm-map", "{objectClass|attribute}",
   1926      1.1     lukem 		2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
   1927      1.1     lukem 		"( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
   1928      1.1     lukem 			"DESC 'maps attributes/objectClasses' "
   1929  1.1.1.3      adam 			"EQUALITY caseIgnoreMatch "
   1930      1.1     lukem 			"SYNTAX OMsDirectoryString "
   1931      1.1     lukem 			"X-ORDERED 'VALUES' )",
   1932      1.1     lukem 		NULL, NULL },
   1933      1.1     lukem 
   1934      1.1     lukem 	{ "rwm-normalize-mapped-attrs", "true|false",
   1935      1.1     lukem 		2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
   1936      1.1     lukem 		"( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
   1937      1.1     lukem 			"DESC 'Normalize mapped attributes/objectClasses' "
   1938      1.1     lukem 			"SYNTAX OMsBoolean "
   1939      1.1     lukem 			"SINGLE-VALUE )",
   1940      1.1     lukem 		NULL, NULL },
   1941      1.1     lukem 
   1942  1.1.1.2     lukem 	{ "rwm-drop-unrequested-attrs", "true|false",
   1943  1.1.1.2     lukem 		2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_DROP_UNREQUESTED, rwm_cf_gen,
   1944  1.1.1.2     lukem 		"( OLcfgOvAt:16.5 NAME 'olcRwmDropUnrequested' "
   1945  1.1.1.2     lukem 			"DESC 'Drop unrequested attributes' "
   1946  1.1.1.2     lukem 			"SYNTAX OMsBoolean "
   1947  1.1.1.2     lukem 			"SINGLE-VALUE )",
   1948  1.1.1.2     lukem 		NULL, NULL },
   1949  1.1.1.2     lukem 
   1950      1.1     lukem 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
   1951      1.1     lukem };
   1952      1.1     lukem 
   1953      1.1     lukem static ConfigOCs rwmocs[] = {
   1954      1.1     lukem 	{ "( OLcfgOvOc:16.1 "
   1955      1.1     lukem 		"NAME 'olcRwmConfig' "
   1956      1.1     lukem 		"DESC 'Rewrite/remap configuration' "
   1957      1.1     lukem 		"SUP olcOverlayConfig "
   1958      1.1     lukem 		"MAY ( "
   1959      1.1     lukem 			"olcRwmRewrite $ "
   1960      1.1     lukem 			"olcRwmTFSupport $ "
   1961      1.1     lukem 			"olcRwmMap $ "
   1962  1.1.1.5  christos 			"olcRwmNormalizeMapped $ "
   1963  1.1.1.5  christos 			"olcRwmDropUnrequested"
   1964      1.1     lukem 			") )",
   1965      1.1     lukem 		Cft_Overlay, rwmcfg, NULL, NULL },
   1966      1.1     lukem 	{ NULL, 0, NULL }
   1967      1.1     lukem };
   1968      1.1     lukem 
   1969      1.1     lukem static void
   1970  1.1.1.3      adam slap_bv_x_ordered_unparse( BerVarray in, BerVarray *out )
   1971      1.1     lukem {
   1972      1.1     lukem 	int		i;
   1973      1.1     lukem 	BerVarray	bva = NULL;
   1974      1.1     lukem 	char		ibuf[32], *ptr;
   1975      1.1     lukem 	struct berval	idx;
   1976      1.1     lukem 
   1977      1.1     lukem 	assert( in != NULL );
   1978      1.1     lukem 
   1979      1.1     lukem 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
   1980      1.1     lukem 		/* count'em */ ;
   1981      1.1     lukem 
   1982      1.1     lukem 	if ( i == 0 ) {
   1983      1.1     lukem 		return;
   1984      1.1     lukem 	}
   1985      1.1     lukem 
   1986      1.1     lukem 	idx.bv_val = ibuf;
   1987      1.1     lukem 
   1988      1.1     lukem 	bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
   1989      1.1     lukem 	BER_BVZERO( &bva[ 0 ] );
   1990      1.1     lukem 
   1991      1.1     lukem 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
   1992      1.1     lukem 		idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
   1993      1.1     lukem 		if ( idx.bv_len >= sizeof( ibuf ) ) {
   1994      1.1     lukem 			ber_bvarray_free( bva );
   1995      1.1     lukem 			return;
   1996      1.1     lukem 		}
   1997      1.1     lukem 
   1998      1.1     lukem 		bva[i].bv_len = idx.bv_len + in[i].bv_len;
   1999      1.1     lukem 		bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
   2000      1.1     lukem 		ptr = lutil_strcopy( bva[i].bv_val, ibuf );
   2001      1.1     lukem 		ptr = lutil_strcopy( ptr, in[i].bv_val );
   2002      1.1     lukem 		*ptr = '\0';
   2003      1.1     lukem 		BER_BVZERO( &bva[ i + 1 ] );
   2004      1.1     lukem 	}
   2005      1.1     lukem 
   2006      1.1     lukem 	*out = bva;
   2007      1.1     lukem }
   2008      1.1     lukem 
   2009      1.1     lukem static int
   2010  1.1.1.3      adam rwm_bva_add(
   2011  1.1.1.3      adam 	BerVarray		*bva,
   2012  1.1.1.2     lukem 	int			idx,
   2013  1.1.1.2     lukem 	char			**argv )
   2014  1.1.1.2     lukem {
   2015  1.1.1.2     lukem 	char		*line;
   2016  1.1.1.2     lukem 	struct berval	bv;
   2017  1.1.1.2     lukem 
   2018  1.1.1.2     lukem 	line = ldap_charray2str( argv, "\" \"" );
   2019  1.1.1.2     lukem 	if ( line != NULL ) {
   2020  1.1.1.2     lukem 		int	len = strlen( argv[ 0 ] );
   2021  1.1.1.2     lukem 
   2022  1.1.1.2     lukem 		ber_str2bv( line, 0, 0, &bv );
   2023  1.1.1.2     lukem 		AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
   2024  1.1.1.2     lukem 			bv.bv_len - ( len + 1 ) );
   2025  1.1.1.2     lukem 		bv.bv_val[ bv.bv_len - 1 ] = '"';
   2026  1.1.1.2     lukem 
   2027  1.1.1.2     lukem 		if ( idx == -1 ) {
   2028  1.1.1.3      adam 			ber_bvarray_add( bva, &bv );
   2029  1.1.1.2     lukem 
   2030  1.1.1.2     lukem 		} else {
   2031  1.1.1.3      adam 			(*bva)[ idx ] = bv;
   2032  1.1.1.2     lukem 		}
   2033  1.1.1.3      adam 
   2034  1.1.1.3      adam 		return 0;
   2035  1.1.1.2     lukem 	}
   2036  1.1.1.2     lukem 
   2037  1.1.1.3      adam 	return -1;
   2038  1.1.1.3      adam }
   2039  1.1.1.3      adam 
   2040  1.1.1.3      adam static int
   2041  1.1.1.3      adam rwm_bva_rewrite_add(
   2042  1.1.1.3      adam 	struct ldaprwmap	*rwmap,
   2043  1.1.1.3      adam 	int			idx,
   2044  1.1.1.3      adam 	char			**argv )
   2045  1.1.1.3      adam {
   2046  1.1.1.3      adam 	return rwm_bva_add( &rwmap->rwm_bva_rewrite, idx, argv );
   2047  1.1.1.3      adam }
   2048  1.1.1.3      adam 
   2049  1.1.1.4      tron #ifdef unused
   2050  1.1.1.3      adam static int
   2051  1.1.1.3      adam rwm_bva_map_add(
   2052  1.1.1.3      adam 	struct ldaprwmap	*rwmap,
   2053  1.1.1.3      adam 	int			idx,
   2054  1.1.1.3      adam 	char			**argv )
   2055  1.1.1.3      adam {
   2056  1.1.1.3      adam 	return rwm_bva_add( &rwmap->rwm_bva_map, idx, argv );
   2057  1.1.1.2     lukem }
   2058  1.1.1.4      tron #endif /* unused */
   2059  1.1.1.2     lukem 
   2060  1.1.1.2     lukem static int
   2061  1.1.1.2     lukem rwm_info_init( struct rewrite_info ** rwm_rw )
   2062  1.1.1.2     lukem {
   2063  1.1.1.2     lukem 	char			*rargv[ 3 ];
   2064  1.1.1.2     lukem 
   2065  1.1.1.2     lukem  	*rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
   2066  1.1.1.2     lukem 	if ( *rwm_rw == NULL ) {
   2067  1.1.1.2     lukem  		return -1;
   2068  1.1.1.2     lukem  	}
   2069  1.1.1.2     lukem 
   2070  1.1.1.2     lukem 	/* this rewriteContext by default must be null;
   2071  1.1.1.2     lukem 	 * rules can be added if required */
   2072  1.1.1.2     lukem 	rargv[ 0 ] = "rewriteContext";
   2073  1.1.1.2     lukem 	rargv[ 1 ] = "searchFilter";
   2074  1.1.1.2     lukem 	rargv[ 2 ] = NULL;
   2075  1.1.1.2     lukem 	rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
   2076  1.1.1.2     lukem 
   2077  1.1.1.2     lukem 	rargv[ 0 ] = "rewriteContext";
   2078  1.1.1.2     lukem 	rargv[ 1 ] = "default";
   2079  1.1.1.2     lukem 	rargv[ 2 ] = NULL;
   2080  1.1.1.2     lukem 	rewrite_parse( *rwm_rw, "<suffix massage>", 2, 2, rargv );
   2081  1.1.1.2     lukem 
   2082  1.1.1.2     lukem 	return 0;
   2083  1.1.1.2     lukem }
   2084  1.1.1.2     lukem 
   2085  1.1.1.2     lukem static int
   2086      1.1     lukem rwm_cf_gen( ConfigArgs *c )
   2087      1.1     lukem {
   2088      1.1     lukem 	slap_overinst		*on = (slap_overinst *)c->bi;
   2089      1.1     lukem 	struct ldaprwmap	*rwmap =
   2090      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   2091      1.1     lukem 
   2092      1.1     lukem 	BackendDB		db;
   2093      1.1     lukem 	char			*argv0;
   2094  1.1.1.2     lukem 	int			idx0 = 0;
   2095      1.1     lukem 	int			rc = 0;
   2096      1.1     lukem 
   2097      1.1     lukem 	db = *c->be;
   2098      1.1     lukem 	db.bd_info = c->bi;
   2099      1.1     lukem 
   2100      1.1     lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
   2101      1.1     lukem 		struct berval	bv = BER_BVNULL;
   2102      1.1     lukem 
   2103      1.1     lukem 		switch ( c->type ) {
   2104      1.1     lukem 		case RWM_CF_REWRITE:
   2105      1.1     lukem 			if ( rwmap->rwm_bva_rewrite == NULL ) {
   2106      1.1     lukem 				rc = 1;
   2107      1.1     lukem 
   2108      1.1     lukem 			} else {
   2109  1.1.1.3      adam 				slap_bv_x_ordered_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
   2110      1.1     lukem 				if ( !c->rvalue_vals ) {
   2111      1.1     lukem 					rc = 1;
   2112      1.1     lukem 				}
   2113      1.1     lukem 			}
   2114      1.1     lukem 			break;
   2115      1.1     lukem 
   2116      1.1     lukem 		case RWM_CF_T_F_SUPPORT:
   2117      1.1     lukem 			enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
   2118      1.1     lukem 			if ( BER_BVISNULL( &bv ) ) {
   2119      1.1     lukem 				/* there's something wrong... */
   2120      1.1     lukem 				assert( 0 );
   2121      1.1     lukem 				rc = 1;
   2122      1.1     lukem 
   2123      1.1     lukem 			} else {
   2124      1.1     lukem 				value_add_one( &c->rvalue_vals, &bv );
   2125      1.1     lukem 			}
   2126      1.1     lukem 			break;
   2127      1.1     lukem 
   2128      1.1     lukem 		case RWM_CF_MAP:
   2129      1.1     lukem 			if ( rwmap->rwm_bva_map == NULL ) {
   2130      1.1     lukem 				rc = 1;
   2131      1.1     lukem 
   2132      1.1     lukem 			} else {
   2133  1.1.1.3      adam 				slap_bv_x_ordered_unparse( rwmap->rwm_bva_map, &c->rvalue_vals );
   2134  1.1.1.3      adam 				if ( !c->rvalue_vals ) {
   2135  1.1.1.3      adam 					rc = 1;
   2136  1.1.1.3      adam 				}
   2137      1.1     lukem 			}
   2138      1.1     lukem 			break;
   2139      1.1     lukem 
   2140      1.1     lukem 		case RWM_CF_NORMALIZE_MAPPED:
   2141      1.1     lukem 			c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
   2142      1.1     lukem 			break;
   2143      1.1     lukem 
   2144  1.1.1.2     lukem 		case RWM_CF_DROP_UNREQUESTED:
   2145  1.1.1.2     lukem 			c->value_int = ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS );
   2146  1.1.1.2     lukem 			break;
   2147  1.1.1.2     lukem 
   2148      1.1     lukem 		default:
   2149      1.1     lukem 			assert( 0 );
   2150      1.1     lukem 			rc = 1;
   2151      1.1     lukem 		}
   2152      1.1     lukem 
   2153      1.1     lukem 		return rc;
   2154      1.1     lukem 
   2155      1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2156      1.1     lukem 		switch ( c->type ) {
   2157      1.1     lukem 		case RWM_CF_REWRITE:
   2158      1.1     lukem 			if ( c->valx >= 0 ) {
   2159  1.1.1.2     lukem 				int i;
   2160  1.1.1.2     lukem 
   2161  1.1.1.2     lukem 				for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
   2162  1.1.1.2     lukem 					/* count'em */ ;
   2163  1.1.1.2     lukem 
   2164  1.1.1.3      adam 				if ( c->valx >= i ) {
   2165  1.1.1.2     lukem 					rc = 1;
   2166  1.1.1.2     lukem 					break;
   2167  1.1.1.2     lukem 				}
   2168  1.1.1.2     lukem 
   2169  1.1.1.2     lukem 				ber_memfree( rwmap->rwm_bva_rewrite[ c->valx ].bv_val );
   2170  1.1.1.2     lukem 				for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i + 1 ] ); i++ )
   2171  1.1.1.2     lukem 				{
   2172  1.1.1.2     lukem 					rwmap->rwm_bva_rewrite[ i ] = rwmap->rwm_bva_rewrite[ i + 1 ];
   2173  1.1.1.2     lukem 				}
   2174  1.1.1.2     lukem 				BER_BVZERO( &rwmap->rwm_bva_rewrite[ i ] );
   2175  1.1.1.2     lukem 
   2176  1.1.1.2     lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   2177  1.1.1.2     lukem 				assert( rwmap->rwm_rw == NULL );
   2178  1.1.1.2     lukem 
   2179  1.1.1.2     lukem 				rc = rwm_info_init( &rwmap->rwm_rw );
   2180  1.1.1.2     lukem 
   2181  1.1.1.2     lukem 				for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
   2182  1.1.1.2     lukem 				{
   2183  1.1.1.3      adam 					ConfigArgs ca = { 0 };
   2184  1.1.1.3      adam 
   2185  1.1.1.2     lukem 					ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
   2186  1.1.1.2     lukem 					ca.argc = 0;
   2187  1.1.1.5  christos 					init_config_argv( &ca );
   2188  1.1.1.5  christos 					config_parse_ldif( &ca );
   2189  1.1.1.5  christos 
   2190  1.1.1.5  christos 					argv0 = ca.argv[ 0 ];
   2191  1.1.1.5  christos 					ca.argv[ 0 ] += STRLENOF( "rwm-" );
   2192  1.1.1.5  christos 
   2193  1.1.1.2     lukem 					if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
   2194  1.1.1.2     lukem 						rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2195  1.1.1.2     lukem 							ca.argc, ca.argv );
   2196  1.1.1.2     lukem 
   2197  1.1.1.2     lukem 					} else {
   2198  1.1.1.2     lukem 						rc = rwm_rw_config( &db, c->fname, c->lineno,
   2199  1.1.1.2     lukem 							ca.argc, ca.argv );
   2200  1.1.1.2     lukem 					}
   2201  1.1.1.2     lukem 
   2202  1.1.1.5  christos 					ca.argv[ 0 ] = argv0;
   2203  1.1.1.5  christos 
   2204  1.1.1.2     lukem 					ch_free( ca.tline );
   2205  1.1.1.3      adam 					ch_free( ca.argv );
   2206  1.1.1.2     lukem 
   2207  1.1.1.2     lukem 					assert( rc == 0 );
   2208  1.1.1.2     lukem 				}
   2209      1.1     lukem 
   2210      1.1     lukem 			} else if ( rwmap->rwm_rw != NULL ) {
   2211      1.1     lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   2212      1.1     lukem 				assert( rwmap->rwm_rw == NULL );
   2213      1.1     lukem 
   2214      1.1     lukem 				ber_bvarray_free( rwmap->rwm_bva_rewrite );
   2215      1.1     lukem 				rwmap->rwm_bva_rewrite = NULL;
   2216  1.1.1.2     lukem 
   2217  1.1.1.2     lukem 				rc = rwm_info_init( &rwmap->rwm_rw );
   2218      1.1     lukem 			}
   2219      1.1     lukem 			break;
   2220      1.1     lukem 
   2221      1.1     lukem 		case RWM_CF_T_F_SUPPORT:
   2222      1.1     lukem 			rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
   2223      1.1     lukem 			break;
   2224      1.1     lukem 
   2225      1.1     lukem 		case RWM_CF_MAP:
   2226      1.1     lukem 			if ( c->valx >= 0 ) {
   2227  1.1.1.3      adam 				struct ldapmap rwm_oc = rwmap->rwm_oc;
   2228  1.1.1.3      adam 				struct ldapmap rwm_at = rwmap->rwm_at;
   2229  1.1.1.3      adam 				char *argv[5];
   2230  1.1.1.3      adam 				int cnt = 0;
   2231  1.1.1.3      adam 
   2232  1.1.1.3      adam 				if ( rwmap->rwm_bva_map ) {
   2233  1.1.1.3      adam 					for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
   2234  1.1.1.3      adam 						/* count */ ;
   2235  1.1.1.3      adam 				}
   2236  1.1.1.3      adam 
   2237  1.1.1.3      adam 				if ( c->valx >= cnt ) {
   2238  1.1.1.3      adam 					rc = 1;
   2239  1.1.1.3      adam 					break;
   2240  1.1.1.3      adam 				}
   2241  1.1.1.3      adam 
   2242  1.1.1.3      adam 				memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
   2243  1.1.1.3      adam 				memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
   2244  1.1.1.3      adam 
   2245  1.1.1.3      adam 				/* re-parse all mappings except the one
   2246  1.1.1.3      adam 				 * that needs to be eliminated */
   2247  1.1.1.3      adam 				argv[0] = "map";
   2248  1.1.1.3      adam 				for ( cnt = 0; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
   2249  1.1.1.3      adam 					ConfigArgs ca = { 0 };
   2250  1.1.1.3      adam 
   2251  1.1.1.3      adam 					if ( cnt == c->valx ) {
   2252  1.1.1.3      adam 						continue;
   2253  1.1.1.3      adam 					}
   2254  1.1.1.3      adam 
   2255  1.1.1.3      adam 					ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
   2256  1.1.1.3      adam 					ca.argc = 0;
   2257  1.1.1.5  christos 					init_config_argv( &ca );
   2258  1.1.1.5  christos 					config_parse_ldif( &ca );
   2259  1.1.1.3      adam 
   2260  1.1.1.3      adam 					argv[1] = ca.argv[0];
   2261  1.1.1.3      adam 					argv[2] = ca.argv[1];
   2262  1.1.1.3      adam 					argv[3] = ca.argv[2];
   2263  1.1.1.3      adam 					argv[4] = ca.argv[3];
   2264  1.1.1.3      adam 
   2265  1.1.1.3      adam 					rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
   2266  1.1.1.3      adam 
   2267  1.1.1.3      adam 					ch_free( ca.tline );
   2268  1.1.1.3      adam 					ch_free( ca.argv );
   2269  1.1.1.3      adam 
   2270  1.1.1.3      adam 					/* in case of failure, restore
   2271  1.1.1.3      adam 					 * the existing mapping */
   2272  1.1.1.3      adam 					if ( rc ) {
   2273  1.1.1.3      adam 						avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2274  1.1.1.3      adam 						avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2275  1.1.1.3      adam 						avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2276  1.1.1.3      adam 						avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2277  1.1.1.3      adam 						rwmap->rwm_oc = rwm_oc;
   2278  1.1.1.3      adam 						rwmap->rwm_at = rwm_at;
   2279  1.1.1.3      adam 						break;
   2280  1.1.1.3      adam 					}
   2281  1.1.1.3      adam 				}
   2282  1.1.1.3      adam 
   2283  1.1.1.3      adam 				/* in case of success, destroy the old mapping
   2284  1.1.1.3      adam 				 * and eliminate the deleted one */
   2285  1.1.1.3      adam 				if ( rc == 0 ) {
   2286  1.1.1.3      adam 					avl_free( rwm_oc.remap, rwm_mapping_dst_free );
   2287  1.1.1.3      adam 					avl_free( rwm_oc.map, rwm_mapping_free );
   2288  1.1.1.3      adam 					avl_free( rwm_at.remap, rwm_mapping_dst_free );
   2289  1.1.1.3      adam 					avl_free( rwm_at.map, rwm_mapping_free );
   2290  1.1.1.3      adam 
   2291  1.1.1.3      adam 					ber_memfree( rwmap->rwm_bva_map[ c->valx ].bv_val );
   2292  1.1.1.3      adam 					for ( cnt = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
   2293  1.1.1.3      adam 						rwmap->rwm_bva_map[ cnt ] = rwmap->rwm_bva_map[ cnt + 1 ];
   2294  1.1.1.3      adam 					}
   2295  1.1.1.3      adam 				}
   2296      1.1     lukem 
   2297      1.1     lukem 			} else {
   2298      1.1     lukem 				avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2299      1.1     lukem 				avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2300      1.1     lukem 				avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2301      1.1     lukem 				avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2302      1.1     lukem 
   2303      1.1     lukem 				rwmap->rwm_oc.remap = NULL;
   2304      1.1     lukem 				rwmap->rwm_oc.map = NULL;
   2305      1.1     lukem 				rwmap->rwm_at.remap = NULL;
   2306      1.1     lukem 				rwmap->rwm_at.map = NULL;
   2307      1.1     lukem 
   2308      1.1     lukem 				ber_bvarray_free( rwmap->rwm_bva_map );
   2309      1.1     lukem 				rwmap->rwm_bva_map = NULL;
   2310      1.1     lukem 			}
   2311      1.1     lukem 			break;
   2312      1.1     lukem 
   2313      1.1     lukem 		case RWM_CF_NORMALIZE_MAPPED:
   2314      1.1     lukem 			rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
   2315      1.1     lukem 			break;
   2316      1.1     lukem 
   2317  1.1.1.2     lukem 		case RWM_CF_DROP_UNREQUESTED:
   2318  1.1.1.2     lukem 			rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
   2319  1.1.1.2     lukem 			break;
   2320  1.1.1.2     lukem 
   2321      1.1     lukem 		default:
   2322      1.1     lukem 			return 1;
   2323      1.1     lukem 		}
   2324      1.1     lukem 		return rc;
   2325      1.1     lukem 	}
   2326      1.1     lukem 
   2327  1.1.1.2     lukem 	if ( strncasecmp( c->argv[ 0 ], "olcRwm", STRLENOF( "olcRwm" ) ) == 0 ) {
   2328  1.1.1.2     lukem 		idx0 = 1;
   2329  1.1.1.2     lukem 	}
   2330  1.1.1.2     lukem 
   2331      1.1     lukem 	switch ( c->type ) {
   2332      1.1     lukem 	case RWM_CF_REWRITE:
   2333  1.1.1.2     lukem 		if ( c->valx >= 0 ) {
   2334  1.1.1.2     lukem 			struct rewrite_info *rwm_rw = rwmap->rwm_rw;
   2335  1.1.1.2     lukem 			int i, last;
   2336  1.1.1.2     lukem 
   2337  1.1.1.2     lukem 			for ( last = 0; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ last ] ); last++ )
   2338  1.1.1.2     lukem 				/* count'em */ ;
   2339  1.1.1.2     lukem 
   2340  1.1.1.2     lukem 			if ( c->valx > last ) {
   2341  1.1.1.2     lukem 				c->valx = last;
   2342  1.1.1.2     lukem 			}
   2343  1.1.1.2     lukem 
   2344  1.1.1.2     lukem 			rwmap->rwm_rw = NULL;
   2345  1.1.1.2     lukem 			rc = rwm_info_init( &rwmap->rwm_rw );
   2346  1.1.1.2     lukem 
   2347  1.1.1.2     lukem 			for ( i = 0; i < c->valx; i++ ) {
   2348  1.1.1.3      adam 				ConfigArgs ca = { 0 };
   2349  1.1.1.3      adam 
   2350  1.1.1.2     lukem 				ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
   2351  1.1.1.2     lukem 				ca.argc = 0;
   2352  1.1.1.5  christos 				init_config_argv( &ca );
   2353  1.1.1.5  christos 				config_parse_ldif( &ca );
   2354  1.1.1.2     lukem 
   2355  1.1.1.2     lukem 				argv0 = ca.argv[ 0 ];
   2356  1.1.1.2     lukem 				ca.argv[ 0 ] += STRLENOF( "rwm-" );
   2357  1.1.1.2     lukem 
   2358  1.1.1.2     lukem 				if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
   2359  1.1.1.2     lukem 					rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2360  1.1.1.2     lukem 						ca.argc, ca.argv );
   2361      1.1     lukem 
   2362  1.1.1.2     lukem 				} else {
   2363  1.1.1.2     lukem 					rc = rwm_rw_config( &db, c->fname, c->lineno,
   2364  1.1.1.2     lukem 						ca.argc, ca.argv );
   2365  1.1.1.2     lukem 				}
   2366      1.1     lukem 
   2367  1.1.1.2     lukem 				ca.argv[ 0 ] = argv0;
   2368      1.1     lukem 
   2369  1.1.1.2     lukem 				ch_free( ca.tline );
   2370  1.1.1.3      adam 				ch_free( ca.argv );
   2371  1.1.1.2     lukem 
   2372  1.1.1.2     lukem 				assert( rc == 0 );
   2373      1.1     lukem 			}
   2374      1.1     lukem 
   2375  1.1.1.2     lukem 			argv0 = c->argv[ idx0 ];
   2376  1.1.1.2     lukem 			if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
   2377  1.1.1.2     lukem 				return 1;
   2378  1.1.1.2     lukem 			}
   2379  1.1.1.2     lukem 			c->argv[ idx0 ] += STRLENOF( "rwm-" );
   2380  1.1.1.2     lukem 			if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
   2381  1.1.1.2     lukem 				rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2382  1.1.1.2     lukem 					c->argc - idx0, &c->argv[ idx0 ] );
   2383      1.1     lukem 
   2384  1.1.1.2     lukem 			} else {
   2385  1.1.1.2     lukem 				rc = rwm_rw_config( &db, c->fname, c->lineno,
   2386  1.1.1.2     lukem 					c->argc - idx0, &c->argv[ idx0 ] );
   2387  1.1.1.2     lukem 			}
   2388  1.1.1.2     lukem 			c->argv[ idx0 ] = argv0;
   2389  1.1.1.2     lukem 			if ( rc != 0 ) {
   2390  1.1.1.2     lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   2391  1.1.1.2     lukem 				assert( rwmap->rwm_rw == NULL );
   2392      1.1     lukem 
   2393  1.1.1.2     lukem 				rwmap->rwm_rw = rwm_rw;
   2394  1.1.1.2     lukem 				return 1;
   2395  1.1.1.2     lukem 			}
   2396      1.1     lukem 
   2397  1.1.1.2     lukem 			for ( i = c->valx; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
   2398  1.1.1.2     lukem 			{
   2399  1.1.1.3      adam 				ConfigArgs ca = { 0 };
   2400  1.1.1.3      adam 
   2401  1.1.1.2     lukem 				ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
   2402  1.1.1.2     lukem 				ca.argc = 0;
   2403  1.1.1.5  christos 				init_config_argv( &ca );
   2404  1.1.1.5  christos 				config_parse_ldif( &ca );
   2405  1.1.1.2     lukem 
   2406  1.1.1.2     lukem 				argv0 = ca.argv[ 0 ];
   2407  1.1.1.2     lukem 				ca.argv[ 0 ] += STRLENOF( "rwm-" );
   2408  1.1.1.2     lukem 
   2409  1.1.1.2     lukem 				if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
   2410  1.1.1.2     lukem 					rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2411  1.1.1.2     lukem 						ca.argc, ca.argv );
   2412      1.1     lukem 
   2413  1.1.1.2     lukem 				} else {
   2414  1.1.1.2     lukem 					rc = rwm_rw_config( &db, c->fname, c->lineno,
   2415  1.1.1.2     lukem 						ca.argc, ca.argv );
   2416  1.1.1.2     lukem 				}
   2417  1.1.1.2     lukem 
   2418  1.1.1.2     lukem 				ca.argv[ 0 ] = argv0;
   2419  1.1.1.2     lukem 
   2420  1.1.1.2     lukem 				ch_free( ca.tline );
   2421  1.1.1.3      adam 				ch_free( ca.argv );
   2422  1.1.1.2     lukem 
   2423  1.1.1.2     lukem 				assert( rc == 0 );
   2424      1.1     lukem 			}
   2425  1.1.1.2     lukem 
   2426  1.1.1.2     lukem 			rwmap->rwm_bva_rewrite = ch_realloc( rwmap->rwm_bva_rewrite,
   2427  1.1.1.2     lukem 				( last + 2 )*sizeof( struct berval ) );
   2428  1.1.1.2     lukem 			BER_BVZERO( &rwmap->rwm_bva_rewrite[last+1] );
   2429  1.1.1.2     lukem 
   2430  1.1.1.2     lukem 			for ( i = last - 1; i >= c->valx; i-- )
   2431  1.1.1.2     lukem 			{
   2432  1.1.1.2     lukem 				rwmap->rwm_bva_rewrite[ i + 1 ] = rwmap->rwm_bva_rewrite[ i ];
   2433  1.1.1.2     lukem 			}
   2434  1.1.1.2     lukem 
   2435  1.1.1.2     lukem 			rwm_bva_rewrite_add( rwmap, c->valx, &c->argv[ idx0 ] );
   2436  1.1.1.2     lukem 
   2437  1.1.1.2     lukem 			rewrite_info_delete( &rwm_rw );
   2438  1.1.1.2     lukem 			assert( rwm_rw == NULL );
   2439  1.1.1.2     lukem 
   2440  1.1.1.2     lukem 			break;
   2441  1.1.1.2     lukem 		}
   2442  1.1.1.2     lukem 
   2443  1.1.1.2     lukem 		argv0 = c->argv[ idx0 ];
   2444  1.1.1.2     lukem 		if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
   2445  1.1.1.2     lukem 			return 1;
   2446  1.1.1.2     lukem 		}
   2447  1.1.1.2     lukem 		c->argv[ idx0 ] += STRLENOF( "rwm-" );
   2448  1.1.1.2     lukem 		if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
   2449  1.1.1.2     lukem 			rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2450  1.1.1.2     lukem 				c->argc - idx0, &c->argv[ idx0 ] );
   2451  1.1.1.2     lukem 
   2452  1.1.1.2     lukem 		} else {
   2453  1.1.1.2     lukem 			rc = rwm_rw_config( &db, c->fname, c->lineno,
   2454  1.1.1.2     lukem 				c->argc - idx0, &c->argv[ idx0 ] );
   2455  1.1.1.2     lukem 		}
   2456  1.1.1.2     lukem 		c->argv[ idx0 ] = argv0;
   2457  1.1.1.2     lukem 		if ( rc ) {
   2458  1.1.1.2     lukem 			return 1;
   2459  1.1.1.2     lukem 
   2460  1.1.1.2     lukem 		} else {
   2461  1.1.1.2     lukem 			rwm_bva_rewrite_add( rwmap, -1, &c->argv[ idx0 ] );
   2462      1.1     lukem 		}
   2463      1.1     lukem 		break;
   2464      1.1     lukem 
   2465      1.1     lukem 	case RWM_CF_T_F_SUPPORT:
   2466      1.1     lukem 		rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
   2467      1.1     lukem 		if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
   2468      1.1     lukem 			return 1;
   2469      1.1     lukem 		}
   2470      1.1     lukem 
   2471      1.1     lukem 		rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
   2472      1.1     lukem 		rwmap->rwm_flags |= t_f_mode[ rc ].mask;
   2473      1.1     lukem 		rc = 0;
   2474      1.1     lukem 		break;
   2475      1.1     lukem 
   2476      1.1     lukem 	case RWM_CF_MAP:
   2477  1.1.1.2     lukem 		if ( c->valx >= 0 ) {
   2478  1.1.1.3      adam 			struct ldapmap rwm_oc = rwmap->rwm_oc;
   2479  1.1.1.3      adam 			struct ldapmap rwm_at = rwmap->rwm_at;
   2480  1.1.1.3      adam 			char *argv[5];
   2481  1.1.1.3      adam 			int cnt = 0;
   2482  1.1.1.3      adam 
   2483  1.1.1.3      adam 			if ( rwmap->rwm_bva_map ) {
   2484  1.1.1.3      adam 				for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
   2485  1.1.1.3      adam 					/* count */ ;
   2486  1.1.1.3      adam 			}
   2487  1.1.1.3      adam 
   2488  1.1.1.3      adam 			if ( c->valx >= cnt ) {
   2489  1.1.1.3      adam 				c->valx = cnt;
   2490  1.1.1.3      adam 			}
   2491  1.1.1.3      adam 
   2492  1.1.1.3      adam 			memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
   2493  1.1.1.3      adam 			memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
   2494  1.1.1.3      adam 
   2495  1.1.1.3      adam 			/* re-parse all mappings, including the one
   2496  1.1.1.3      adam 			 * that needs to be added */
   2497  1.1.1.3      adam 			argv[0] = "map";
   2498  1.1.1.3      adam 			for ( cnt = 0; cnt < c->valx; cnt++ ) {
   2499  1.1.1.3      adam 				ConfigArgs ca = { 0 };
   2500  1.1.1.3      adam 
   2501  1.1.1.3      adam 				ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
   2502  1.1.1.3      adam 				ca.argc = 0;
   2503  1.1.1.5  christos 				init_config_argv( &ca );
   2504  1.1.1.5  christos 				config_parse_ldif( &ca );
   2505  1.1.1.3      adam 
   2506  1.1.1.3      adam 				argv[1] = ca.argv[0];
   2507  1.1.1.3      adam 				argv[2] = ca.argv[1];
   2508  1.1.1.3      adam 				argv[3] = ca.argv[2];
   2509  1.1.1.3      adam 				argv[4] = ca.argv[3];
   2510  1.1.1.3      adam 
   2511  1.1.1.3      adam 				rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
   2512  1.1.1.3      adam 
   2513  1.1.1.3      adam 				ch_free( ca.tline );
   2514  1.1.1.3      adam 				ch_free( ca.argv );
   2515  1.1.1.3      adam 
   2516  1.1.1.3      adam 				/* in case of failure, restore
   2517  1.1.1.3      adam 				 * the existing mapping */
   2518  1.1.1.3      adam 				if ( rc ) {
   2519  1.1.1.3      adam 					goto rwmmap_fail;
   2520  1.1.1.3      adam 				}
   2521  1.1.1.3      adam 			}
   2522  1.1.1.3      adam 
   2523  1.1.1.3      adam 			argv0 = c->argv[0];
   2524  1.1.1.3      adam 			c->argv[0] = "map";
   2525  1.1.1.3      adam 			rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
   2526  1.1.1.3      adam 			c->argv[0] = argv0;
   2527  1.1.1.3      adam 			if ( rc ) {
   2528  1.1.1.3      adam 				goto rwmmap_fail;
   2529  1.1.1.3      adam 			}
   2530  1.1.1.3      adam 
   2531  1.1.1.3      adam 			if ( rwmap->rwm_bva_map ) {
   2532  1.1.1.3      adam 				for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
   2533  1.1.1.3      adam 					ConfigArgs ca = { 0 };
   2534  1.1.1.3      adam 
   2535  1.1.1.3      adam 					ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
   2536  1.1.1.3      adam 					ca.argc = 0;
   2537  1.1.1.5  christos 					init_config_argv( &ca );
   2538  1.1.1.5  christos 					config_parse_ldif( &ca );
   2539  1.1.1.3      adam 
   2540  1.1.1.3      adam 					argv[1] = ca.argv[0];
   2541  1.1.1.3      adam 					argv[2] = ca.argv[1];
   2542  1.1.1.3      adam 					argv[3] = ca.argv[2];
   2543  1.1.1.3      adam 					argv[4] = ca.argv[3];
   2544  1.1.1.3      adam 
   2545  1.1.1.3      adam 					rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
   2546  1.1.1.3      adam 
   2547  1.1.1.3      adam 					ch_free( ca.tline );
   2548  1.1.1.3      adam 					ch_free( ca.argv );
   2549  1.1.1.3      adam 
   2550  1.1.1.3      adam 					/* in case of failure, restore
   2551  1.1.1.3      adam 					 * the existing mapping */
   2552  1.1.1.3      adam 					if ( rc ) {
   2553  1.1.1.3      adam 						goto rwmmap_fail;
   2554  1.1.1.3      adam 					}
   2555  1.1.1.3      adam 				}
   2556  1.1.1.3      adam 			}
   2557  1.1.1.3      adam 
   2558  1.1.1.3      adam 			/* in case of success, destroy the old mapping
   2559  1.1.1.3      adam 			 * and add the new one */
   2560  1.1.1.3      adam 			if ( rc == 0 ) {
   2561  1.1.1.3      adam 				BerVarray tmp;
   2562  1.1.1.3      adam 				struct berval bv, *bvp = &bv;
   2563  1.1.1.3      adam 
   2564  1.1.1.3      adam 				if ( rwm_bva_add( &bvp, 0, &c->argv[ idx0 ] ) ) {
   2565  1.1.1.3      adam 					rc = 1;
   2566  1.1.1.3      adam 					goto rwmmap_fail;
   2567  1.1.1.3      adam 				}
   2568  1.1.1.3      adam 
   2569  1.1.1.3      adam 				tmp = ber_memrealloc( rwmap->rwm_bva_map,
   2570  1.1.1.3      adam 					sizeof( struct berval )*( cnt + 2 ) );
   2571  1.1.1.3      adam 				if ( tmp == NULL ) {
   2572  1.1.1.3      adam 					ber_memfree( bv.bv_val );
   2573  1.1.1.3      adam 					rc = 1;
   2574  1.1.1.3      adam 					goto rwmmap_fail;
   2575  1.1.1.3      adam 				}
   2576  1.1.1.3      adam 				rwmap->rwm_bva_map = tmp;
   2577  1.1.1.3      adam 				BER_BVZERO( &rwmap->rwm_bva_map[ cnt + 1 ] );
   2578  1.1.1.3      adam 
   2579  1.1.1.3      adam 				avl_free( rwm_oc.remap, rwm_mapping_dst_free );
   2580  1.1.1.3      adam 				avl_free( rwm_oc.map, rwm_mapping_free );
   2581  1.1.1.3      adam 				avl_free( rwm_at.remap, rwm_mapping_dst_free );
   2582  1.1.1.3      adam 				avl_free( rwm_at.map, rwm_mapping_free );
   2583  1.1.1.3      adam 
   2584  1.1.1.3      adam 				for ( ; cnt-- > c->valx; ) {
   2585  1.1.1.3      adam 					rwmap->rwm_bva_map[ cnt + 1 ] = rwmap->rwm_bva_map[ cnt ];
   2586  1.1.1.3      adam 				}
   2587  1.1.1.3      adam 				rwmap->rwm_bva_map[ c->valx ] = bv;
   2588  1.1.1.3      adam 
   2589  1.1.1.3      adam 			} else {
   2590  1.1.1.3      adam rwmmap_fail:;
   2591  1.1.1.3      adam 				avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2592  1.1.1.3      adam 				avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2593  1.1.1.3      adam 				avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2594  1.1.1.3      adam 				avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2595  1.1.1.3      adam 				rwmap->rwm_oc = rwm_oc;
   2596  1.1.1.3      adam 				rwmap->rwm_at = rwm_at;
   2597  1.1.1.3      adam 			}
   2598  1.1.1.3      adam 
   2599  1.1.1.3      adam 			break;
   2600  1.1.1.2     lukem 		}
   2601  1.1.1.2     lukem 
   2602      1.1     lukem 		argv0 = c->argv[ 0 ];
   2603      1.1     lukem 		c->argv[ 0 ] += STRLENOF( "rwm-" );
   2604      1.1     lukem 		rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
   2605      1.1     lukem 		c->argv[ 0 ] = argv0;
   2606      1.1     lukem 		if ( rc ) {
   2607      1.1     lukem 			return 1;
   2608      1.1     lukem 
   2609      1.1     lukem 		} else {
   2610      1.1     lukem 			char		*line;
   2611      1.1     lukem 			struct berval	bv;
   2612      1.1     lukem 
   2613      1.1     lukem 			line = ldap_charray2str( &c->argv[ 1 ], " " );
   2614      1.1     lukem 			if ( line != NULL ) {
   2615      1.1     lukem 				ber_str2bv( line, 0, 0, &bv );
   2616      1.1     lukem 				ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
   2617      1.1     lukem 			}
   2618      1.1     lukem 		}
   2619      1.1     lukem 		break;
   2620      1.1     lukem 
   2621      1.1     lukem 	case RWM_CF_NORMALIZE_MAPPED:
   2622      1.1     lukem 		if ( c->value_int ) {
   2623      1.1     lukem 			rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
   2624      1.1     lukem 		} else {
   2625      1.1     lukem 			rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
   2626      1.1     lukem 		}
   2627      1.1     lukem 		break;
   2628      1.1     lukem 
   2629  1.1.1.2     lukem 	case RWM_CF_DROP_UNREQUESTED:
   2630  1.1.1.2     lukem 		if ( c->value_int ) {
   2631  1.1.1.2     lukem 			rwmap->rwm_flags |= RWM_F_DROP_UNREQUESTED_ATTRS;
   2632  1.1.1.2     lukem 		} else {
   2633  1.1.1.2     lukem 			rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
   2634  1.1.1.2     lukem 		}
   2635  1.1.1.2     lukem 		break;
   2636  1.1.1.2     lukem 
   2637      1.1     lukem 	default:
   2638      1.1     lukem 		assert( 0 );
   2639      1.1     lukem 		return 1;
   2640      1.1     lukem 	}
   2641      1.1     lukem 
   2642      1.1     lukem 	return rc;
   2643      1.1     lukem }
   2644      1.1     lukem 
   2645      1.1     lukem static int
   2646      1.1     lukem rwm_db_init(
   2647      1.1     lukem 	BackendDB	*be,
   2648      1.1     lukem 	ConfigReply	*cr )
   2649      1.1     lukem {
   2650      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   2651      1.1     lukem 	struct ldaprwmap	*rwmap;
   2652      1.1     lukem 	int			rc = 0;
   2653      1.1     lukem 
   2654      1.1     lukem 	rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
   2655      1.1     lukem 
   2656  1.1.1.2     lukem 	/* default */
   2657  1.1.1.2     lukem 	rwmap->rwm_flags = RWM_F_DROP_UNREQUESTED_ATTRS;
   2658      1.1     lukem 
   2659  1.1.1.2     lukem 	rc = rwm_info_init( &rwmap->rwm_rw );
   2660      1.1     lukem 
   2661      1.1     lukem 	on->on_bi.bi_private = (void *)rwmap;
   2662      1.1     lukem 
   2663      1.1     lukem 	if ( rc ) {
   2664      1.1     lukem 		(void)rwm_db_destroy( be, NULL );
   2665      1.1     lukem 	}
   2666      1.1     lukem 
   2667      1.1     lukem 	return rc;
   2668      1.1     lukem }
   2669      1.1     lukem 
   2670      1.1     lukem static int
   2671      1.1     lukem rwm_db_destroy(
   2672      1.1     lukem 	BackendDB	*be,
   2673      1.1     lukem 	ConfigReply	*cr )
   2674      1.1     lukem {
   2675      1.1     lukem 	slap_overinst	*on = (slap_overinst *) be->bd_info;
   2676      1.1     lukem 	int		rc = 0;
   2677      1.1     lukem 
   2678      1.1     lukem 	if ( on->on_bi.bi_private ) {
   2679      1.1     lukem 		struct ldaprwmap	*rwmap =
   2680      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   2681      1.1     lukem 
   2682      1.1     lukem 		if ( rwmap->rwm_rw ) {
   2683      1.1     lukem 			rewrite_info_delete( &rwmap->rwm_rw );
   2684  1.1.1.2     lukem 			if ( rwmap->rwm_bva_rewrite )
   2685  1.1.1.2     lukem 				ber_bvarray_free( rwmap->rwm_bva_rewrite );
   2686      1.1     lukem 		}
   2687      1.1     lukem 
   2688      1.1     lukem 		avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2689      1.1     lukem 		avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2690      1.1     lukem 		avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2691      1.1     lukem 		avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2692      1.1     lukem 		ber_bvarray_free( rwmap->rwm_bva_map );
   2693      1.1     lukem 
   2694      1.1     lukem 		ch_free( rwmap );
   2695      1.1     lukem 	}
   2696      1.1     lukem 
   2697      1.1     lukem 	return rc;
   2698      1.1     lukem }
   2699      1.1     lukem 
   2700      1.1     lukem static slap_overinst rwm = { { NULL } };
   2701      1.1     lukem 
   2702      1.1     lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
   2703      1.1     lukem static
   2704      1.1     lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
   2705      1.1     lukem int
   2706      1.1     lukem rwm_initialize( void )
   2707      1.1     lukem {
   2708      1.1     lukem 	int		rc;
   2709      1.1     lukem 
   2710      1.1     lukem 	/* Make sure we don't exceed the bits reserved for userland */
   2711      1.1     lukem 	config_check_userland( RWM_CF_LAST );
   2712      1.1     lukem 
   2713      1.1     lukem 	memset( &rwm, 0, sizeof( slap_overinst ) );
   2714      1.1     lukem 
   2715      1.1     lukem 	rwm.on_bi.bi_type = "rwm";
   2716      1.1     lukem 	rwm.on_bi.bi_flags =
   2717      1.1     lukem 		SLAPO_BFLAG_SINGLE |
   2718      1.1     lukem 		0;
   2719      1.1     lukem 
   2720      1.1     lukem 	rwm.on_bi.bi_db_init = rwm_db_init;
   2721      1.1     lukem 	rwm.on_bi.bi_db_config = rwm_db_config;
   2722      1.1     lukem 	rwm.on_bi.bi_db_destroy = rwm_db_destroy;
   2723      1.1     lukem 
   2724      1.1     lukem 	rwm.on_bi.bi_op_bind = rwm_op_bind;
   2725      1.1     lukem 	rwm.on_bi.bi_op_search = rwm_op_search;
   2726      1.1     lukem 	rwm.on_bi.bi_op_compare = rwm_op_compare;
   2727      1.1     lukem 	rwm.on_bi.bi_op_modify = rwm_op_modify;
   2728      1.1     lukem 	rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
   2729      1.1     lukem 	rwm.on_bi.bi_op_add = rwm_op_add;
   2730      1.1     lukem 	rwm.on_bi.bi_op_delete = rwm_op_delete;
   2731      1.1     lukem 	rwm.on_bi.bi_op_unbind = rwm_op_unbind;
   2732      1.1     lukem 	rwm.on_bi.bi_extended = rwm_extended;
   2733  1.1.1.2     lukem #if 1 /* TODO */
   2734  1.1.1.2     lukem 	rwm.on_bi.bi_entry_release_rw = rwm_entry_release_rw;
   2735  1.1.1.2     lukem 	rwm.on_bi.bi_entry_get_rw = rwm_entry_get_rw;
   2736  1.1.1.2     lukem #endif
   2737      1.1     lukem 
   2738      1.1     lukem 	rwm.on_bi.bi_operational = rwm_operational;
   2739      1.1     lukem 	rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
   2740      1.1     lukem 
   2741      1.1     lukem 	rwm.on_bi.bi_connection_init = rwm_conn_init;
   2742      1.1     lukem 	rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
   2743      1.1     lukem 
   2744      1.1     lukem 	rwm.on_response = rwm_response;
   2745      1.1     lukem 
   2746      1.1     lukem 	rwm.on_bi.bi_cf_ocs = rwmocs;
   2747      1.1     lukem 
   2748      1.1     lukem 	rc = config_register_schema( rwmcfg, rwmocs );
   2749      1.1     lukem 	if ( rc ) {
   2750      1.1     lukem 		return rc;
   2751      1.1     lukem 	}
   2752      1.1     lukem 
   2753      1.1     lukem 	return overlay_register( &rwm );
   2754      1.1     lukem }
   2755      1.1     lukem 
   2756      1.1     lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
   2757      1.1     lukem int
   2758      1.1     lukem init_module( int argc, char *argv[] )
   2759      1.1     lukem {
   2760      1.1     lukem 	return rwm_initialize();
   2761      1.1     lukem }
   2762      1.1     lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
   2763      1.1     lukem 
   2764      1.1     lukem #endif /* SLAPD_OVER_RWM */
   2765