Home | History | Annotate | Line # | Download | only in overlays
rwm.c revision 1.1.1.1
      1  1.1  lukem /* rwm.c - rewrite/remap operations */
      2  1.1  lukem /* $OpenLDAP: pkg/ldap/servers/slapd/overlays/rwm.c,v 1.70.2.10 2008/02/15 18:11:46 quanah Exp $ */
      3  1.1  lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      4  1.1  lukem  *
      5  1.1  lukem  * Copyright 2003-2008 The OpenLDAP Foundation.
      6  1.1  lukem  * Portions Copyright 2003 Pierangelo Masarati.
      7  1.1  lukem  * All rights reserved.
      8  1.1  lukem  *
      9  1.1  lukem  * Redistribution and use in source and binary forms, with or without
     10  1.1  lukem  * modification, are permitted only as authorized by the OpenLDAP
     11  1.1  lukem  * Public License.
     12  1.1  lukem  *
     13  1.1  lukem  * A copy of this license is available in the file LICENSE in the
     14  1.1  lukem  * top-level directory of the distribution or, alternatively, at
     15  1.1  lukem  * <http://www.OpenLDAP.org/license.html>.
     16  1.1  lukem  */
     17  1.1  lukem 
     18  1.1  lukem #include "portable.h"
     19  1.1  lukem 
     20  1.1  lukem #ifdef SLAPD_OVER_RWM
     21  1.1  lukem 
     22  1.1  lukem #include <stdio.h>
     23  1.1  lukem 
     24  1.1  lukem #include <ac/string.h>
     25  1.1  lukem 
     26  1.1  lukem #include "slap.h"
     27  1.1  lukem #include "config.h"
     28  1.1  lukem #include "lutil.h"
     29  1.1  lukem #include "rwm.h"
     30  1.1  lukem 
     31  1.1  lukem typedef struct rwm_op_state {
     32  1.1  lukem 	ber_tag_t r_tag;
     33  1.1  lukem 	struct berval ro_dn;
     34  1.1  lukem 	struct berval ro_ndn;
     35  1.1  lukem 	struct berval r_dn;
     36  1.1  lukem 	struct berval r_ndn;
     37  1.1  lukem 	AttributeName *mapped_attrs;
     38  1.1  lukem 	OpRequest o_request;
     39  1.1  lukem } rwm_op_state;
     40  1.1  lukem 
     41  1.1  lukem static int
     42  1.1  lukem rwm_db_destroy( BackendDB *be, ConfigReply *cr );
     43  1.1  lukem 
     44  1.1  lukem typedef struct rwm_op_cb {
     45  1.1  lukem 	slap_callback cb;
     46  1.1  lukem 	rwm_op_state ros;
     47  1.1  lukem } rwm_op_cb;
     48  1.1  lukem 
     49  1.1  lukem static int
     50  1.1  lukem rwm_op_cleanup( Operation *op, SlapReply *rs )
     51  1.1  lukem {
     52  1.1  lukem 	slap_callback	*cb = op->o_callback;
     53  1.1  lukem 	rwm_op_state *ros = cb->sc_private;
     54  1.1  lukem 
     55  1.1  lukem 	if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
     56  1.1  lukem 		op->o_abandon || rs->sr_err == SLAPD_ABANDON ) {
     57  1.1  lukem 
     58  1.1  lukem 		op->o_req_dn = ros->ro_dn;
     59  1.1  lukem 		op->o_req_ndn = ros->ro_ndn;
     60  1.1  lukem 
     61  1.1  lukem 		if ( !BER_BVISNULL( &ros->r_dn )
     62  1.1  lukem 			&& ros->r_dn.bv_val != ros->r_ndn.bv_val )
     63  1.1  lukem 		{
     64  1.1  lukem 			ch_free( ros->r_dn.bv_val );
     65  1.1  lukem 			BER_BVZERO( &ros->r_dn );
     66  1.1  lukem 		}
     67  1.1  lukem 
     68  1.1  lukem 		if ( !BER_BVISNULL( &ros->r_ndn ) ) {
     69  1.1  lukem 			ch_free( ros->r_ndn.bv_val );
     70  1.1  lukem 			BER_BVZERO( &ros->r_ndn );
     71  1.1  lukem 		}
     72  1.1  lukem 
     73  1.1  lukem 		switch( ros->r_tag ) {
     74  1.1  lukem 		case LDAP_REQ_COMPARE:
     75  1.1  lukem 			if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
     76  1.1  lukem 				op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
     77  1.1  lukem 			op->orc_ava = ros->orc_ava;
     78  1.1  lukem 			break;
     79  1.1  lukem 		case LDAP_REQ_MODIFY:
     80  1.1  lukem 			slap_mods_free( op->orm_modlist, 1 );
     81  1.1  lukem 			op->orm_modlist = ros->orm_modlist;
     82  1.1  lukem 			break;
     83  1.1  lukem 		case LDAP_REQ_MODRDN:
     84  1.1  lukem 			if ( op->orr_newSup != ros->orr_newSup ) {
     85  1.1  lukem 				ch_free( op->orr_newSup->bv_val );
     86  1.1  lukem 				ch_free( op->orr_nnewSup->bv_val );
     87  1.1  lukem 				op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
     88  1.1  lukem 				op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
     89  1.1  lukem 				op->orr_newSup = ros->orr_newSup;
     90  1.1  lukem 				op->orr_nnewSup = ros->orr_nnewSup;
     91  1.1  lukem 			}
     92  1.1  lukem 			break;
     93  1.1  lukem 		case LDAP_REQ_SEARCH:
     94  1.1  lukem 			ch_free( ros->mapped_attrs );
     95  1.1  lukem 			filter_free_x( op, op->ors_filter );
     96  1.1  lukem 			ch_free( op->ors_filterstr.bv_val );
     97  1.1  lukem 			op->ors_attrs = ros->ors_attrs;
     98  1.1  lukem 			op->ors_filter = ros->ors_filter;
     99  1.1  lukem 			op->ors_filterstr = ros->ors_filterstr;
    100  1.1  lukem 			break;
    101  1.1  lukem 		case LDAP_REQ_EXTENDED:
    102  1.1  lukem 			if ( op->ore_reqdata != ros->ore_reqdata ) {
    103  1.1  lukem 				ber_bvfree( op->ore_reqdata );
    104  1.1  lukem 				op->ore_reqdata = ros->ore_reqdata;
    105  1.1  lukem 			}
    106  1.1  lukem 			break;
    107  1.1  lukem 		default:	break;
    108  1.1  lukem 		}
    109  1.1  lukem 		op->o_callback = op->o_callback->sc_next;
    110  1.1  lukem 		op->o_tmpfree( cb, op->o_tmpmemctx );
    111  1.1  lukem 	}
    112  1.1  lukem 
    113  1.1  lukem 	return SLAP_CB_CONTINUE;
    114  1.1  lukem }
    115  1.1  lukem 
    116  1.1  lukem static rwm_op_cb *
    117  1.1  lukem rwm_callback_get( Operation *op, SlapReply *rs )
    118  1.1  lukem {
    119  1.1  lukem 	rwm_op_cb	*roc = NULL;
    120  1.1  lukem 
    121  1.1  lukem 	roc = op->o_tmpalloc( sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
    122  1.1  lukem 	roc->cb.sc_cleanup = rwm_op_cleanup;
    123  1.1  lukem 	roc->cb.sc_response = NULL;
    124  1.1  lukem 	roc->cb.sc_next = op->o_callback;
    125  1.1  lukem 	roc->cb.sc_private = &roc->ros;
    126  1.1  lukem 	roc->ros.r_tag = op->o_tag;
    127  1.1  lukem 	roc->ros.ro_dn = op->o_req_dn;
    128  1.1  lukem 	roc->ros.ro_ndn = op->o_req_ndn;
    129  1.1  lukem 	roc->ros.o_request = op->o_request;
    130  1.1  lukem 	BER_BVZERO( &roc->ros.r_dn );
    131  1.1  lukem 	BER_BVZERO( &roc->ros.r_ndn );
    132  1.1  lukem 
    133  1.1  lukem 	return roc;
    134  1.1  lukem }
    135  1.1  lukem 
    136  1.1  lukem 
    137  1.1  lukem static int
    138  1.1  lukem rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
    139  1.1  lukem 	rwm_op_state *ros )
    140  1.1  lukem {
    141  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    142  1.1  lukem 	struct ldaprwmap	*rwmap =
    143  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    144  1.1  lukem 
    145  1.1  lukem 	struct berval		dn = BER_BVNULL,
    146  1.1  lukem 				ndn = BER_BVNULL;
    147  1.1  lukem 	int			rc = 0;
    148  1.1  lukem 	dncookie		dc;
    149  1.1  lukem 
    150  1.1  lukem 	/*
    151  1.1  lukem 	 * Rewrite the dn if needed
    152  1.1  lukem 	 */
    153  1.1  lukem 	dc.rwmap = rwmap;
    154  1.1  lukem 	dc.conn = op->o_conn;
    155  1.1  lukem 	dc.rs = rs;
    156  1.1  lukem 	dc.ctx = (char *)cookie;
    157  1.1  lukem 
    158  1.1  lukem 	/* NOTE: in those cases where only the ndn is available,
    159  1.1  lukem 	 * and the caller sets op->o_req_dn = op->o_req_ndn,
    160  1.1  lukem 	 * only rewrite the op->o_req_ndn and use it as
    161  1.1  lukem 	 * op->o_req_dn as well */
    162  1.1  lukem 	ndn = op->o_req_ndn;
    163  1.1  lukem 	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
    164  1.1  lukem 		dn = op->o_req_dn;
    165  1.1  lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
    166  1.1  lukem 	} else {
    167  1.1  lukem 		rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
    168  1.1  lukem 	}
    169  1.1  lukem 
    170  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    171  1.1  lukem 		return rc;
    172  1.1  lukem 	}
    173  1.1  lukem 
    174  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 )
    175  1.1  lukem 			|| ndn.bv_val == op->o_req_ndn.bv_val )
    176  1.1  lukem 	{
    177  1.1  lukem 		return LDAP_SUCCESS;
    178  1.1  lukem 	}
    179  1.1  lukem 
    180  1.1  lukem 	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
    181  1.1  lukem 		op->o_req_dn = dn;
    182  1.1  lukem 		ros->r_dn = dn;
    183  1.1  lukem 	} else {
    184  1.1  lukem 		op->o_req_dn = ndn;
    185  1.1  lukem 	}
    186  1.1  lukem 	op->o_req_ndn = ndn;
    187  1.1  lukem 	ros->r_ndn = ndn;
    188  1.1  lukem 
    189  1.1  lukem 	return LDAP_SUCCESS;
    190  1.1  lukem }
    191  1.1  lukem 
    192  1.1  lukem static int
    193  1.1  lukem rwm_op_add( Operation *op, SlapReply *rs )
    194  1.1  lukem {
    195  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    196  1.1  lukem 	struct ldaprwmap	*rwmap =
    197  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    198  1.1  lukem 
    199  1.1  lukem 	int			rc,
    200  1.1  lukem 				i;
    201  1.1  lukem 	Attribute		**ap = NULL;
    202  1.1  lukem 	char			*olddn = op->o_req_dn.bv_val;
    203  1.1  lukem 	int			isupdate;
    204  1.1  lukem 
    205  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    206  1.1  lukem 
    207  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
    208  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    209  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    210  1.1  lukem 		send_ldap_error( op, rs, rc, "addDN massage error" );
    211  1.1  lukem 		return -1;
    212  1.1  lukem 	}
    213  1.1  lukem 
    214  1.1  lukem 	if ( olddn != op->o_req_dn.bv_val ) {
    215  1.1  lukem 		ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
    216  1.1  lukem 		ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
    217  1.1  lukem 	}
    218  1.1  lukem 
    219  1.1  lukem 	/* Count number of attributes in entry */
    220  1.1  lukem 	isupdate = be_shadow_update( op );
    221  1.1  lukem 	for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
    222  1.1  lukem 		Attribute	*a;
    223  1.1  lukem 
    224  1.1  lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
    225  1.1  lukem 				(*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
    226  1.1  lukem 		{
    227  1.1  lukem 			int		j, last;
    228  1.1  lukem 
    229  1.1  lukem 			last = (*ap)->a_numvals - 1;
    230  1.1  lukem 			for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
    231  1.1  lukem 				struct ldapmapping	*mapping = NULL;
    232  1.1  lukem 
    233  1.1  lukem 				( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
    234  1.1  lukem 						&mapping, RWM_MAP );
    235  1.1  lukem 				if ( mapping == NULL ) {
    236  1.1  lukem 					if ( rwmap->rwm_at.drop_missing ) {
    237  1.1  lukem 						/* FIXME: we allow to remove objectClasses as well;
    238  1.1  lukem 						 * if the resulting entry is inconsistent, that's
    239  1.1  lukem 						 * the relayed database's business...
    240  1.1  lukem 						 */
    241  1.1  lukem 						ch_free( (*ap)->a_vals[ j ].bv_val );
    242  1.1  lukem 						if ( last > j ) {
    243  1.1  lukem 							(*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
    244  1.1  lukem 						}
    245  1.1  lukem 						BER_BVZERO( &(*ap)->a_vals[ last ] );
    246  1.1  lukem 						(*ap)->a_numvals--;
    247  1.1  lukem 						last--;
    248  1.1  lukem 						j--;
    249  1.1  lukem 					}
    250  1.1  lukem 
    251  1.1  lukem 				} else {
    252  1.1  lukem 					ch_free( (*ap)->a_vals[ j ].bv_val );
    253  1.1  lukem 					ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
    254  1.1  lukem 				}
    255  1.1  lukem 			}
    256  1.1  lukem 
    257  1.1  lukem 		} else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
    258  1.1  lukem 		{
    259  1.1  lukem 			goto next_attr;
    260  1.1  lukem 
    261  1.1  lukem 		} else {
    262  1.1  lukem 			struct ldapmapping	*mapping = NULL;
    263  1.1  lukem 
    264  1.1  lukem 			( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
    265  1.1  lukem 					&mapping, RWM_MAP );
    266  1.1  lukem 			if ( mapping == NULL ) {
    267  1.1  lukem 				if ( rwmap->rwm_at.drop_missing ) {
    268  1.1  lukem 					goto cleanup_attr;
    269  1.1  lukem 				}
    270  1.1  lukem 			}
    271  1.1  lukem 
    272  1.1  lukem 			if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    273  1.1  lukem 					|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    274  1.1  lukem 			{
    275  1.1  lukem 				/*
    276  1.1  lukem 				 * FIXME: rewrite could fail; in this case
    277  1.1  lukem 				 * the operation should give up, right?
    278  1.1  lukem 				 */
    279  1.1  lukem 				rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
    280  1.1  lukem 						(*ap)->a_vals,
    281  1.1  lukem 						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
    282  1.1  lukem 				if ( rc ) {
    283  1.1  lukem 					goto cleanup_attr;
    284  1.1  lukem 				}
    285  1.1  lukem 
    286  1.1  lukem 			} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
    287  1.1  lukem 				rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
    288  1.1  lukem 						(*ap)->a_vals,
    289  1.1  lukem 						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
    290  1.1  lukem 				if ( rc != LDAP_SUCCESS ) {
    291  1.1  lukem 					goto cleanup_attr;
    292  1.1  lukem 				}
    293  1.1  lukem 			}
    294  1.1  lukem 
    295  1.1  lukem 			if ( mapping != NULL ) {
    296  1.1  lukem 				assert( mapping->m_dst_ad != NULL );
    297  1.1  lukem 				(*ap)->a_desc = mapping->m_dst_ad;
    298  1.1  lukem 			}
    299  1.1  lukem 		}
    300  1.1  lukem 
    301  1.1  lukem next_attr:;
    302  1.1  lukem 		ap = &(*ap)->a_next;
    303  1.1  lukem 		continue;
    304  1.1  lukem 
    305  1.1  lukem cleanup_attr:;
    306  1.1  lukem 		/* FIXME: leaking attribute/values? */
    307  1.1  lukem 		a = *ap;
    308  1.1  lukem 
    309  1.1  lukem 		*ap = (*ap)->a_next;
    310  1.1  lukem 		attr_free( a );
    311  1.1  lukem 	}
    312  1.1  lukem 
    313  1.1  lukem 	op->o_callback = &roc->cb;
    314  1.1  lukem 
    315  1.1  lukem 	return SLAP_CB_CONTINUE;
    316  1.1  lukem }
    317  1.1  lukem 
    318  1.1  lukem static int
    319  1.1  lukem rwm_conn_init( BackendDB *be, Connection *conn )
    320  1.1  lukem {
    321  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
    322  1.1  lukem 	struct ldaprwmap	*rwmap =
    323  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    324  1.1  lukem 
    325  1.1  lukem 	( void )rewrite_session_init( rwmap->rwm_rw, conn );
    326  1.1  lukem 
    327  1.1  lukem 	return SLAP_CB_CONTINUE;
    328  1.1  lukem }
    329  1.1  lukem 
    330  1.1  lukem static int
    331  1.1  lukem rwm_conn_destroy( BackendDB *be, Connection *conn )
    332  1.1  lukem {
    333  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
    334  1.1  lukem 	struct ldaprwmap	*rwmap =
    335  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    336  1.1  lukem 
    337  1.1  lukem 	( void )rewrite_session_delete( rwmap->rwm_rw, conn );
    338  1.1  lukem 
    339  1.1  lukem 	return SLAP_CB_CONTINUE;
    340  1.1  lukem }
    341  1.1  lukem 
    342  1.1  lukem static int
    343  1.1  lukem rwm_op_bind( Operation *op, SlapReply *rs )
    344  1.1  lukem {
    345  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    346  1.1  lukem 	int			rc;
    347  1.1  lukem 
    348  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    349  1.1  lukem 
    350  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
    351  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    352  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    353  1.1  lukem 		send_ldap_error( op, rs, rc, "bindDN massage error" );
    354  1.1  lukem 		return -1;
    355  1.1  lukem 	}
    356  1.1  lukem 
    357  1.1  lukem 	op->o_callback = &roc->cb;
    358  1.1  lukem 
    359  1.1  lukem 	return SLAP_CB_CONTINUE;
    360  1.1  lukem }
    361  1.1  lukem 
    362  1.1  lukem static int
    363  1.1  lukem rwm_op_unbind( Operation *op, SlapReply *rs )
    364  1.1  lukem {
    365  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    366  1.1  lukem 	struct ldaprwmap	*rwmap =
    367  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    368  1.1  lukem 
    369  1.1  lukem 	rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
    370  1.1  lukem 
    371  1.1  lukem 	return SLAP_CB_CONTINUE;
    372  1.1  lukem }
    373  1.1  lukem 
    374  1.1  lukem static int
    375  1.1  lukem rwm_op_compare( Operation *op, SlapReply *rs )
    376  1.1  lukem {
    377  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    378  1.1  lukem 	struct ldaprwmap	*rwmap =
    379  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    380  1.1  lukem 
    381  1.1  lukem 	int			rc;
    382  1.1  lukem 	struct berval		mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
    383  1.1  lukem 
    384  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    385  1.1  lukem 
    386  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
    387  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    388  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    389  1.1  lukem 		send_ldap_error( op, rs, rc, "compareDN massage error" );
    390  1.1  lukem 		return -1;
    391  1.1  lukem 	}
    392  1.1  lukem 
    393  1.1  lukem 	/* if the attribute is an objectClass, try to remap its value */
    394  1.1  lukem 	if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
    395  1.1  lukem 			|| op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
    396  1.1  lukem 	{
    397  1.1  lukem 		rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
    398  1.1  lukem 				&mapped_vals[0], RWM_MAP );
    399  1.1  lukem 		if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
    400  1.1  lukem 		{
    401  1.1  lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    402  1.1  lukem 			send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
    403  1.1  lukem 			return -1;
    404  1.1  lukem 
    405  1.1  lukem 		} else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
    406  1.1  lukem 			ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
    407  1.1  lukem 				op->o_tmpmemctx );
    408  1.1  lukem 		}
    409  1.1  lukem 
    410  1.1  lukem 	} else {
    411  1.1  lukem 		struct ldapmapping	*mapping = NULL;
    412  1.1  lukem 		AttributeDescription	*ad = op->orc_ava->aa_desc;
    413  1.1  lukem 
    414  1.1  lukem 		( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
    415  1.1  lukem 				&mapping, RWM_MAP );
    416  1.1  lukem 		if ( mapping == NULL ) {
    417  1.1  lukem 			if ( rwmap->rwm_at.drop_missing ) {
    418  1.1  lukem 				op->o_bd->bd_info = (BackendInfo *)on->on_info;
    419  1.1  lukem 				send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
    420  1.1  lukem 				return -1;
    421  1.1  lukem 			}
    422  1.1  lukem 
    423  1.1  lukem 		} else {
    424  1.1  lukem 			assert( mapping->m_dst_ad != NULL );
    425  1.1  lukem 			ad = mapping->m_dst_ad;
    426  1.1  lukem 		}
    427  1.1  lukem 
    428  1.1  lukem 		if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    429  1.1  lukem 				|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    430  1.1  lukem 		{
    431  1.1  lukem 			struct berval	*mapped_valsp[2];
    432  1.1  lukem 
    433  1.1  lukem 			mapped_valsp[0] = &mapped_vals[0];
    434  1.1  lukem 			mapped_valsp[1] = &mapped_vals[1];
    435  1.1  lukem 
    436  1.1  lukem 			mapped_vals[0] = op->orc_ava->aa_value;
    437  1.1  lukem 
    438  1.1  lukem 			rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
    439  1.1  lukem 
    440  1.1  lukem 			if ( rc != LDAP_SUCCESS ) {
    441  1.1  lukem 				op->o_bd->bd_info = (BackendInfo *)on->on_info;
    442  1.1  lukem 				send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
    443  1.1  lukem 				return -1;
    444  1.1  lukem 			}
    445  1.1  lukem 
    446  1.1  lukem 			if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
    447  1.1  lukem 				/* NOTE: if we get here, rwm_dnattr_rewrite()
    448  1.1  lukem 				 * already freed the old value, so now
    449  1.1  lukem 				 * it's invalid */
    450  1.1  lukem 				ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
    451  1.1  lukem 					op->o_tmpmemctx );
    452  1.1  lukem 				ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
    453  1.1  lukem 			}
    454  1.1  lukem 		}
    455  1.1  lukem 		op->orc_ava->aa_desc = ad;
    456  1.1  lukem 	}
    457  1.1  lukem 
    458  1.1  lukem 	op->o_callback = &roc->cb;
    459  1.1  lukem 
    460  1.1  lukem 	return SLAP_CB_CONTINUE;
    461  1.1  lukem }
    462  1.1  lukem 
    463  1.1  lukem static int
    464  1.1  lukem rwm_op_delete( Operation *op, SlapReply *rs )
    465  1.1  lukem {
    466  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    467  1.1  lukem 	int			rc;
    468  1.1  lukem 
    469  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    470  1.1  lukem 
    471  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
    472  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    473  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    474  1.1  lukem 		send_ldap_error( op, rs, rc, "deleteDN massage error" );
    475  1.1  lukem 		return -1;
    476  1.1  lukem 	}
    477  1.1  lukem 
    478  1.1  lukem 	op->o_callback = &roc->cb;
    479  1.1  lukem 
    480  1.1  lukem 	return SLAP_CB_CONTINUE;
    481  1.1  lukem }
    482  1.1  lukem 
    483  1.1  lukem static int
    484  1.1  lukem rwm_op_modify( Operation *op, SlapReply *rs )
    485  1.1  lukem {
    486  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    487  1.1  lukem 	struct ldaprwmap	*rwmap =
    488  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    489  1.1  lukem 
    490  1.1  lukem 	int			isupdate;
    491  1.1  lukem 	Modifications		**mlp;
    492  1.1  lukem 	int			rc;
    493  1.1  lukem 
    494  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    495  1.1  lukem 
    496  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
    497  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    498  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    499  1.1  lukem 		send_ldap_error( op, rs, rc, "modifyDN massage error" );
    500  1.1  lukem 		return -1;
    501  1.1  lukem 	}
    502  1.1  lukem 
    503  1.1  lukem 	isupdate = be_shadow_update( op );
    504  1.1  lukem 	for ( mlp = &op->orm_modlist; *mlp; ) {
    505  1.1  lukem 		int			is_oc = 0;
    506  1.1  lukem 		Modifications		*ml = *mlp;
    507  1.1  lukem 		struct ldapmapping	*mapping = NULL;
    508  1.1  lukem 
    509  1.1  lukem 		/* ml points to a temporary mod until needs duplication */
    510  1.1  lukem 		if ( ml->sml_desc == slap_schema.si_ad_objectClass
    511  1.1  lukem 				|| ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
    512  1.1  lukem 		{
    513  1.1  lukem 			is_oc = 1;
    514  1.1  lukem 
    515  1.1  lukem 		} else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
    516  1.1  lukem 		{
    517  1.1  lukem 			ml = ch_malloc( sizeof( Modifications ) );
    518  1.1  lukem 			*ml = **mlp;
    519  1.1  lukem 			if ( (*mlp)->sml_values ) {
    520  1.1  lukem 				ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
    521  1.1  lukem 				if ( (*mlp)->sml_nvalues ) {
    522  1.1  lukem 					ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
    523  1.1  lukem 				}
    524  1.1  lukem 			}
    525  1.1  lukem 			*mlp = ml;
    526  1.1  lukem 			goto next_mod;
    527  1.1  lukem 
    528  1.1  lukem 		} else {
    529  1.1  lukem 			int			drop_missing;
    530  1.1  lukem 
    531  1.1  lukem 			drop_missing = rwm_mapping( &rwmap->rwm_at,
    532  1.1  lukem 					&ml->sml_desc->ad_cname,
    533  1.1  lukem 					&mapping, RWM_MAP );
    534  1.1  lukem 			if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
    535  1.1  lukem 			{
    536  1.1  lukem 				goto cleanup_mod;
    537  1.1  lukem 			}
    538  1.1  lukem 		}
    539  1.1  lukem 
    540  1.1  lukem 		/* duplicate the modlist */
    541  1.1  lukem 		ml = ch_malloc( sizeof( Modifications ));
    542  1.1  lukem 		*ml = **mlp;
    543  1.1  lukem 		*mlp = ml;
    544  1.1  lukem 
    545  1.1  lukem 		if ( ml->sml_values != NULL ) {
    546  1.1  lukem 			int i, num;
    547  1.1  lukem 			struct berval *bva;
    548  1.1  lukem 
    549  1.1  lukem 			for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
    550  1.1  lukem 				/* count values */ ;
    551  1.1  lukem 
    552  1.1  lukem 			bva = ch_malloc( (num+1) * sizeof( struct berval ));
    553  1.1  lukem 			for (i=0; i<num; i++)
    554  1.1  lukem 				ber_dupbv( &bva[i], &ml->sml_values[i] );
    555  1.1  lukem 			BER_BVZERO( &bva[i] );
    556  1.1  lukem 			ml->sml_values = bva;
    557  1.1  lukem 
    558  1.1  lukem 			if ( ml->sml_nvalues ) {
    559  1.1  lukem 				bva = ch_malloc( (num+1) * sizeof( struct berval ));
    560  1.1  lukem 				for (i=0; i<num; i++)
    561  1.1  lukem 					ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
    562  1.1  lukem 				BER_BVZERO( &bva[i] );
    563  1.1  lukem 				ml->sml_nvalues = bva;
    564  1.1  lukem 			}
    565  1.1  lukem 
    566  1.1  lukem 			if ( is_oc ) {
    567  1.1  lukem 				int	last, j;
    568  1.1  lukem 
    569  1.1  lukem 				last = num-1;
    570  1.1  lukem 
    571  1.1  lukem 				for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
    572  1.1  lukem 					struct ldapmapping	*oc_mapping = NULL;
    573  1.1  lukem 
    574  1.1  lukem 					( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
    575  1.1  lukem 							&oc_mapping, RWM_MAP );
    576  1.1  lukem 					if ( oc_mapping == NULL ) {
    577  1.1  lukem 						if ( rwmap->rwm_at.drop_missing ) {
    578  1.1  lukem 							/* FIXME: we allow to remove objectClasses as well;
    579  1.1  lukem 							 * if the resulting entry is inconsistent, that's
    580  1.1  lukem 							 * the relayed database's business...
    581  1.1  lukem 							 */
    582  1.1  lukem 							if ( last > j ) {
    583  1.1  lukem 								ch_free( ml->sml_values[ j ].bv_val );
    584  1.1  lukem 								ml->sml_values[ j ] = ml->sml_values[ last ];
    585  1.1  lukem 							}
    586  1.1  lukem 							BER_BVZERO( &ml->sml_values[ last ] );
    587  1.1  lukem 							last--;
    588  1.1  lukem 							j--;
    589  1.1  lukem 						}
    590  1.1  lukem 
    591  1.1  lukem 					} else {
    592  1.1  lukem 						ch_free( ml->sml_values[ j ].bv_val );
    593  1.1  lukem 						ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
    594  1.1  lukem 					}
    595  1.1  lukem 				}
    596  1.1  lukem 
    597  1.1  lukem 			} else {
    598  1.1  lukem 				if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    599  1.1  lukem 						|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    600  1.1  lukem 				{
    601  1.1  lukem 					rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
    602  1.1  lukem 							ml->sml_values,
    603  1.1  lukem 							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
    604  1.1  lukem 
    605  1.1  lukem 				} else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
    606  1.1  lukem 					rc = rwm_referral_rewrite( op, rs,
    607  1.1  lukem 							"referralAttrDN",
    608  1.1  lukem 							ml->sml_values,
    609  1.1  lukem 							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
    610  1.1  lukem 					if ( rc != LDAP_SUCCESS ) {
    611  1.1  lukem 						goto cleanup_mod;
    612  1.1  lukem 					}
    613  1.1  lukem 				}
    614  1.1  lukem 
    615  1.1  lukem 				if ( rc != LDAP_SUCCESS ) {
    616  1.1  lukem 					goto cleanup_mod;
    617  1.1  lukem 				}
    618  1.1  lukem 			}
    619  1.1  lukem 		}
    620  1.1  lukem 
    621  1.1  lukem next_mod:;
    622  1.1  lukem 		if ( mapping != NULL ) {
    623  1.1  lukem 			/* use new attribute description */
    624  1.1  lukem 			assert( mapping->m_dst_ad != NULL );
    625  1.1  lukem 			ml->sml_desc = mapping->m_dst_ad;
    626  1.1  lukem 		}
    627  1.1  lukem 
    628  1.1  lukem 		mlp = &ml->sml_next;
    629  1.1  lukem 		continue;
    630  1.1  lukem 
    631  1.1  lukem cleanup_mod:;
    632  1.1  lukem 		ml = *mlp;
    633  1.1  lukem 		*mlp = (*mlp)->sml_next;
    634  1.1  lukem 		slap_mod_free( &ml->sml_mod, 0 );
    635  1.1  lukem 		free( ml );
    636  1.1  lukem 	}
    637  1.1  lukem 
    638  1.1  lukem 	op->o_callback = &roc->cb;
    639  1.1  lukem 
    640  1.1  lukem 	return SLAP_CB_CONTINUE;
    641  1.1  lukem }
    642  1.1  lukem 
    643  1.1  lukem static int
    644  1.1  lukem rwm_op_modrdn( Operation *op, SlapReply *rs )
    645  1.1  lukem {
    646  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    647  1.1  lukem 	struct ldaprwmap	*rwmap =
    648  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    649  1.1  lukem 
    650  1.1  lukem 	int			rc;
    651  1.1  lukem 
    652  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    653  1.1  lukem 
    654  1.1  lukem 	if ( op->orr_newSup ) {
    655  1.1  lukem 		dncookie	dc;
    656  1.1  lukem 		struct berval	nnewSup = BER_BVNULL;
    657  1.1  lukem 		struct berval	newSup = BER_BVNULL;
    658  1.1  lukem 
    659  1.1  lukem 		/*
    660  1.1  lukem 		 * Rewrite the new superior, if defined and required
    661  1.1  lukem 	 	 */
    662  1.1  lukem 		dc.rwmap = rwmap;
    663  1.1  lukem 		dc.conn = op->o_conn;
    664  1.1  lukem 		dc.rs = rs;
    665  1.1  lukem 		dc.ctx = "newSuperiorDN";
    666  1.1  lukem 		newSup = *op->orr_newSup;
    667  1.1  lukem 		nnewSup = *op->orr_nnewSup;
    668  1.1  lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
    669  1.1  lukem 		if ( rc != LDAP_SUCCESS ) {
    670  1.1  lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    671  1.1  lukem 			send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
    672  1.1  lukem 			return -1;
    673  1.1  lukem 		}
    674  1.1  lukem 
    675  1.1  lukem 		if ( op->orr_newSup->bv_val != newSup.bv_val ) {
    676  1.1  lukem 			op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
    677  1.1  lukem 				op->o_tmpmemctx );
    678  1.1  lukem 			op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
    679  1.1  lukem 				op->o_tmpmemctx );
    680  1.1  lukem 			*op->orr_newSup = newSup;
    681  1.1  lukem 			*op->orr_nnewSup = nnewSup;
    682  1.1  lukem 		}
    683  1.1  lukem 	}
    684  1.1  lukem 
    685  1.1  lukem 	/*
    686  1.1  lukem 	 * Rewrite the dn, if needed
    687  1.1  lukem  	 */
    688  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
    689  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    690  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    691  1.1  lukem 		send_ldap_error( op, rs, rc, "renameDN massage error" );
    692  1.1  lukem 		if ( op->orr_newSup != roc->ros.orr_newSup ) {
    693  1.1  lukem 			ch_free( op->orr_newSup->bv_val );
    694  1.1  lukem 			ch_free( op->orr_nnewSup->bv_val );
    695  1.1  lukem 			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
    696  1.1  lukem 			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
    697  1.1  lukem 			op->orr_newSup = roc->ros.orr_newSup;
    698  1.1  lukem 			op->orr_nnewSup = roc->ros.orr_nnewSup;
    699  1.1  lukem 		}
    700  1.1  lukem 		return -1;
    701  1.1  lukem 	}
    702  1.1  lukem 
    703  1.1  lukem 	/* TODO: rewrite newRDN, attribute types,
    704  1.1  lukem 	 * values of DN-valued attributes ... */
    705  1.1  lukem 
    706  1.1  lukem 	op->o_callback = &roc->cb;
    707  1.1  lukem 
    708  1.1  lukem 	return SLAP_CB_CONTINUE;
    709  1.1  lukem }
    710  1.1  lukem 
    711  1.1  lukem 
    712  1.1  lukem static int
    713  1.1  lukem rwm_swap_attrs( Operation *op, SlapReply *rs )
    714  1.1  lukem {
    715  1.1  lukem 	slap_callback	*cb = op->o_callback;
    716  1.1  lukem 	rwm_op_state *ros = cb->sc_private;
    717  1.1  lukem 
    718  1.1  lukem 	rs->sr_attrs = ros->ors_attrs;
    719  1.1  lukem 
    720  1.1  lukem 	/* other overlays might have touched op->ors_attrs,
    721  1.1  lukem 	 * so we restore the original version here, otherwise
    722  1.1  lukem 	 * attribute-mapping might fail */
    723  1.1  lukem 	op->ors_attrs = ros->mapped_attrs;
    724  1.1  lukem 
    725  1.1  lukem  	return SLAP_CB_CONTINUE;
    726  1.1  lukem }
    727  1.1  lukem 
    728  1.1  lukem static int
    729  1.1  lukem rwm_op_search( Operation *op, SlapReply *rs )
    730  1.1  lukem {
    731  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    732  1.1  lukem 	struct ldaprwmap	*rwmap =
    733  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    734  1.1  lukem 
    735  1.1  lukem 	int			rc;
    736  1.1  lukem 	dncookie		dc;
    737  1.1  lukem 
    738  1.1  lukem 	struct berval		fstr = BER_BVNULL;
    739  1.1  lukem 	Filter			*f = NULL;
    740  1.1  lukem 
    741  1.1  lukem 	AttributeName		*an = NULL;
    742  1.1  lukem 
    743  1.1  lukem 	char			*text = NULL;
    744  1.1  lukem 
    745  1.1  lukem 	rwm_op_cb		*roc = rwm_callback_get( op, rs );
    746  1.1  lukem 
    747  1.1  lukem 	rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
    748  1.1  lukem 		"searchFilter", op->ors_filterstr.bv_val );
    749  1.1  lukem 	if ( rc == LDAP_SUCCESS )
    750  1.1  lukem 		rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
    751  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    752  1.1  lukem 		text = "searchDN massage error";
    753  1.1  lukem 		goto error_return;
    754  1.1  lukem 	}
    755  1.1  lukem 
    756  1.1  lukem 	/*
    757  1.1  lukem 	 * Rewrite the dn if needed
    758  1.1  lukem 	 */
    759  1.1  lukem 	dc.rwmap = rwmap;
    760  1.1  lukem 	dc.conn = op->o_conn;
    761  1.1  lukem 	dc.rs = rs;
    762  1.1  lukem 	dc.ctx = "searchFilterAttrDN";
    763  1.1  lukem 
    764  1.1  lukem 	rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
    765  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    766  1.1  lukem 		text = "searchFilter/searchFilterAttrDN massage error";
    767  1.1  lukem 		goto error_return;
    768  1.1  lukem 	}
    769  1.1  lukem 
    770  1.1  lukem 	f = str2filter_x( op, fstr.bv_val );
    771  1.1  lukem 
    772  1.1  lukem 	if ( f == NULL ) {
    773  1.1  lukem 		text = "massaged filter parse error";
    774  1.1  lukem 		goto error_return;
    775  1.1  lukem 	}
    776  1.1  lukem 
    777  1.1  lukem 	op->ors_filter = f;
    778  1.1  lukem 	op->ors_filterstr = fstr;
    779  1.1  lukem 
    780  1.1  lukem 	rc = rwm_map_attrnames( &rwmap->rwm_at, &rwmap->rwm_oc,
    781  1.1  lukem 			op->ors_attrs, &an, RWM_MAP );
    782  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    783  1.1  lukem 		text = "attribute list mapping error";
    784  1.1  lukem 		goto error_return;
    785  1.1  lukem 	}
    786  1.1  lukem 
    787  1.1  lukem 	op->ors_attrs = an;
    788  1.1  lukem 	/* store the mapped Attributes for later usage, in
    789  1.1  lukem 	 * the case that other overlays change op->ors_attrs */
    790  1.1  lukem 	roc->ros.mapped_attrs = an;
    791  1.1  lukem 	roc->cb.sc_response = rwm_swap_attrs;
    792  1.1  lukem 
    793  1.1  lukem 	op->o_callback = &roc->cb;
    794  1.1  lukem 
    795  1.1  lukem 	return SLAP_CB_CONTINUE;
    796  1.1  lukem 
    797  1.1  lukem error_return:;
    798  1.1  lukem 	if ( an != NULL ) {
    799  1.1  lukem 		ch_free( an );
    800  1.1  lukem 	}
    801  1.1  lukem 
    802  1.1  lukem 	if ( f != NULL ) {
    803  1.1  lukem 		filter_free_x( op, f );
    804  1.1  lukem 	}
    805  1.1  lukem 
    806  1.1  lukem 	if ( !BER_BVISNULL( &fstr ) ) {
    807  1.1  lukem 		ch_free( fstr.bv_val );
    808  1.1  lukem 	}
    809  1.1  lukem 
    810  1.1  lukem 	op->oq_search = roc->ros.oq_search;
    811  1.1  lukem 
    812  1.1  lukem 	op->o_bd->bd_info = (BackendInfo *)on->on_info;
    813  1.1  lukem 	send_ldap_error( op, rs, rc, text );
    814  1.1  lukem 
    815  1.1  lukem 	return -1;
    816  1.1  lukem 
    817  1.1  lukem }
    818  1.1  lukem 
    819  1.1  lukem static int
    820  1.1  lukem rwm_exop_passwd( Operation *op, SlapReply *rs )
    821  1.1  lukem {
    822  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    823  1.1  lukem 	int			rc;
    824  1.1  lukem 	rwm_op_cb *roc;
    825  1.1  lukem 
    826  1.1  lukem 	struct berval	id = BER_BVNULL,
    827  1.1  lukem 			pwold = BER_BVNULL,
    828  1.1  lukem 			pwnew = BER_BVNULL;
    829  1.1  lukem 	BerElement *ber = NULL;
    830  1.1  lukem 
    831  1.1  lukem 	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
    832  1.1  lukem 		return LDAP_SUCCESS;
    833  1.1  lukem 	}
    834  1.1  lukem 
    835  1.1  lukem 	if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
    836  1.1  lukem 		rs->sr_err = LDAP_OTHER;
    837  1.1  lukem 		return rs->sr_err;
    838  1.1  lukem 	}
    839  1.1  lukem 
    840  1.1  lukem 	rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
    841  1.1  lukem 		&pwold, &pwnew, &rs->sr_text );
    842  1.1  lukem 	if ( rs->sr_err != LDAP_SUCCESS ) {
    843  1.1  lukem 		return rs->sr_err;
    844  1.1  lukem 	}
    845  1.1  lukem 
    846  1.1  lukem 	if ( !BER_BVISNULL( &id ) ) {
    847  1.1  lukem 		char idNul = id.bv_val[id.bv_len];
    848  1.1  lukem 		id.bv_val[id.bv_len] = '\0';
    849  1.1  lukem 		rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
    850  1.1  lukem 				&op->o_req_ndn, op->o_tmpmemctx );
    851  1.1  lukem 		id.bv_val[id.bv_len] = idNul;
    852  1.1  lukem 		if ( rs->sr_err != LDAP_SUCCESS ) {
    853  1.1  lukem 			rs->sr_text = "Invalid DN";
    854  1.1  lukem 			return rs->sr_err;
    855  1.1  lukem 		}
    856  1.1  lukem 
    857  1.1  lukem 	} else {
    858  1.1  lukem 		ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
    859  1.1  lukem 		ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
    860  1.1  lukem 	}
    861  1.1  lukem 
    862  1.1  lukem 	roc = rwm_callback_get( op, rs );
    863  1.1  lukem 
    864  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
    865  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    866  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    867  1.1  lukem 		send_ldap_error( op, rs, rc, "extendedDN massage error" );
    868  1.1  lukem 		return -1;
    869  1.1  lukem 	}
    870  1.1  lukem 
    871  1.1  lukem 	ber = ber_alloc_t( LBER_USE_DER );
    872  1.1  lukem 	if ( !ber ) {
    873  1.1  lukem 		rs->sr_err = LDAP_OTHER;
    874  1.1  lukem 		rs->sr_text = "No memory";
    875  1.1  lukem 		return rs->sr_err;
    876  1.1  lukem 	}
    877  1.1  lukem 	ber_printf( ber, "{" );
    878  1.1  lukem 	if ( !BER_BVISNULL( &id )) {
    879  1.1  lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
    880  1.1  lukem 			&op->o_req_dn );
    881  1.1  lukem 	}
    882  1.1  lukem 	if ( !BER_BVISNULL( &pwold )) {
    883  1.1  lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
    884  1.1  lukem 	}
    885  1.1  lukem 	if ( !BER_BVISNULL( &pwnew )) {
    886  1.1  lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
    887  1.1  lukem 	}
    888  1.1  lukem 	ber_printf( ber, "N}" );
    889  1.1  lukem 	ber_flatten( ber, &op->ore_reqdata );
    890  1.1  lukem 	ber_free( ber, 1 );
    891  1.1  lukem 
    892  1.1  lukem 	op->o_callback = &roc->cb;
    893  1.1  lukem 
    894  1.1  lukem 	return SLAP_CB_CONTINUE;
    895  1.1  lukem }
    896  1.1  lukem 
    897  1.1  lukem static struct exop {
    898  1.1  lukem 	struct berval	oid;
    899  1.1  lukem 	BI_op_extended	*extended;
    900  1.1  lukem } exop_table[] = {
    901  1.1  lukem 	{ BER_BVC(LDAP_EXOP_MODIFY_PASSWD),	rwm_exop_passwd },
    902  1.1  lukem 	{ BER_BVNULL, NULL }
    903  1.1  lukem };
    904  1.1  lukem 
    905  1.1  lukem static int
    906  1.1  lukem rwm_extended( Operation *op, SlapReply *rs )
    907  1.1  lukem {
    908  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    909  1.1  lukem 	int			rc;
    910  1.1  lukem 	rwm_op_cb *roc;
    911  1.1  lukem 
    912  1.1  lukem 	int	i;
    913  1.1  lukem 
    914  1.1  lukem 	for ( i = 0; exop_table[i].extended != NULL; i++ ) {
    915  1.1  lukem 		if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
    916  1.1  lukem 		{
    917  1.1  lukem 			rc = exop_table[i].extended( op, rs );
    918  1.1  lukem 			switch ( rc ) {
    919  1.1  lukem 			case LDAP_SUCCESS:
    920  1.1  lukem 				break;
    921  1.1  lukem 
    922  1.1  lukem 			case SLAP_CB_CONTINUE:
    923  1.1  lukem 			case SLAPD_ABANDON:
    924  1.1  lukem 				return rc;
    925  1.1  lukem 
    926  1.1  lukem 			default:
    927  1.1  lukem 				send_ldap_result( op, rs );
    928  1.1  lukem 				return rc;
    929  1.1  lukem 			}
    930  1.1  lukem 			break;
    931  1.1  lukem 		}
    932  1.1  lukem 	}
    933  1.1  lukem 
    934  1.1  lukem 	roc = rwm_callback_get( op, rs );
    935  1.1  lukem 
    936  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
    937  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    938  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    939  1.1  lukem 		send_ldap_error( op, rs, rc, "extendedDN massage error" );
    940  1.1  lukem 		return -1;
    941  1.1  lukem 	}
    942  1.1  lukem 
    943  1.1  lukem 	/* TODO: rewrite/map extended data ? ... */
    944  1.1  lukem 	op->o_callback = &roc->cb;
    945  1.1  lukem 
    946  1.1  lukem 	return SLAP_CB_CONTINUE;
    947  1.1  lukem }
    948  1.1  lukem 
    949  1.1  lukem static int
    950  1.1  lukem rwm_matched( Operation *op, SlapReply *rs )
    951  1.1  lukem {
    952  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    953  1.1  lukem 	struct ldaprwmap	*rwmap =
    954  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    955  1.1  lukem 
    956  1.1  lukem 	struct berval		dn, mdn;
    957  1.1  lukem 	dncookie		dc;
    958  1.1  lukem 	int			rc;
    959  1.1  lukem 
    960  1.1  lukem 	if ( rs->sr_matched == NULL ) {
    961  1.1  lukem 		return SLAP_CB_CONTINUE;
    962  1.1  lukem 	}
    963  1.1  lukem 
    964  1.1  lukem 	dc.rwmap = rwmap;
    965  1.1  lukem 	dc.conn = op->o_conn;
    966  1.1  lukem 	dc.rs = rs;
    967  1.1  lukem 	dc.ctx = "matchedDN";
    968  1.1  lukem 	ber_str2bv( rs->sr_matched, 0, 0, &dn );
    969  1.1  lukem 	mdn = dn;
    970  1.1  lukem 	rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
    971  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
    972  1.1  lukem 		rs->sr_err = rc;
    973  1.1  lukem 		rs->sr_text = "Rewrite error";
    974  1.1  lukem 		return 1;
    975  1.1  lukem 	}
    976  1.1  lukem 
    977  1.1  lukem 	if ( mdn.bv_val != dn.bv_val ) {
    978  1.1  lukem 		if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
    979  1.1  lukem 			ch_free( (void *)rs->sr_matched );
    980  1.1  lukem 
    981  1.1  lukem 		} else {
    982  1.1  lukem 			rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
    983  1.1  lukem 		}
    984  1.1  lukem 		rs->sr_matched = mdn.bv_val;
    985  1.1  lukem 	}
    986  1.1  lukem 
    987  1.1  lukem 	return SLAP_CB_CONTINUE;
    988  1.1  lukem }
    989  1.1  lukem 
    990  1.1  lukem static int
    991  1.1  lukem rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
    992  1.1  lukem {
    993  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    994  1.1  lukem 	struct ldaprwmap	*rwmap =
    995  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    996  1.1  lukem 
    997  1.1  lukem 	dncookie		dc;
    998  1.1  lukem 	int			rc;
    999  1.1  lukem 	Attribute		**ap;
   1000  1.1  lukem 	int			isupdate;
   1001  1.1  lukem 	int			check_duplicate_attrs = 0;
   1002  1.1  lukem 
   1003  1.1  lukem 	/*
   1004  1.1  lukem 	 * Rewrite the dn attrs, if needed
   1005  1.1  lukem 	 */
   1006  1.1  lukem 	dc.rwmap = rwmap;
   1007  1.1  lukem 	dc.conn = op->o_conn;
   1008  1.1  lukem 	dc.rs = NULL;
   1009  1.1  lukem 
   1010  1.1  lukem 	/* FIXME: the entries are in the remote mapping form;
   1011  1.1  lukem 	 * so we need to select those attributes we are willing
   1012  1.1  lukem 	 * to return, and remap them accordingly */
   1013  1.1  lukem 
   1014  1.1  lukem 	/* FIXME: in principle, one could map an attribute
   1015  1.1  lukem 	 * on top of another, which already exists.
   1016  1.1  lukem 	 * As such, in the end there might exist more than
   1017  1.1  lukem 	 * one instance of an attribute.
   1018  1.1  lukem 	 * We should at least check if this occurs, and issue
   1019  1.1  lukem 	 * an error (because multiple instances of attrs in
   1020  1.1  lukem 	 * response are not valid), or merge the values (what
   1021  1.1  lukem 	 * about duplicate values?) */
   1022  1.1  lukem 	isupdate = be_shadow_update( op );
   1023  1.1  lukem 	for ( ap = a_first; *ap; ) {
   1024  1.1  lukem 		struct ldapmapping	*mapping = NULL;
   1025  1.1  lukem 		int			drop_missing;
   1026  1.1  lukem 		int			last = -1;
   1027  1.1  lukem 		Attribute		*a;
   1028  1.1  lukem 
   1029  1.1  lukem 		if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
   1030  1.1  lukem 		{
   1031  1.1  lukem 			/* go on */ ;
   1032  1.1  lukem 
   1033  1.1  lukem 		} else {
   1034  1.1  lukem 			if ( op->ors_attrs != NULL &&
   1035  1.1  lukem 					!SLAP_USERATTRS( rs->sr_attr_flags ) &&
   1036  1.1  lukem 					!ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
   1037  1.1  lukem 			{
   1038  1.1  lukem 				goto cleanup_attr;
   1039  1.1  lukem 			}
   1040  1.1  lukem 
   1041  1.1  lukem 			drop_missing = rwm_mapping( &rwmap->rwm_at,
   1042  1.1  lukem 					&(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
   1043  1.1  lukem 			if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
   1044  1.1  lukem 			{
   1045  1.1  lukem 				goto cleanup_attr;
   1046  1.1  lukem 			}
   1047  1.1  lukem 			if ( mapping != NULL ) {
   1048  1.1  lukem 				assert( mapping->m_dst_ad != NULL );
   1049  1.1  lukem 
   1050  1.1  lukem 				/* try to normalize mapped Attributes if the original
   1051  1.1  lukem 				 * AttributeType was not normalized */
   1052  1.1  lukem 				if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS) &&
   1053  1.1  lukem 					(!(*ap)->a_desc->ad_type->sat_equality ||
   1054  1.1  lukem 					!(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
   1055  1.1  lukem 					mapping->m_dst_ad->ad_type->sat_equality &&
   1056  1.1  lukem 					mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
   1057  1.1  lukem 				{
   1058  1.1  lukem 					int i = 0;
   1059  1.1  lukem 
   1060  1.1  lukem 					last = (*ap)->a_numvals;
   1061  1.1  lukem 					if ( last )
   1062  1.1  lukem 					{
   1063  1.1  lukem 						(*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
   1064  1.1  lukem 
   1065  1.1  lukem 						for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
   1066  1.1  lukem 							int		rc;
   1067  1.1  lukem 							/*
   1068  1.1  lukem 							 * check that each value is valid per syntax
   1069  1.1  lukem 							 * and pretty if appropriate
   1070  1.1  lukem 							 */
   1071  1.1  lukem 							rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
   1072  1.1  lukem 								SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
   1073  1.1  lukem 								mapping->m_dst_ad->ad_type->sat_syntax,
   1074  1.1  lukem 								mapping->m_dst_ad->ad_type->sat_equality,
   1075  1.1  lukem 								&(*ap)->a_vals[i], &(*ap)->a_nvals[i],
   1076  1.1  lukem 								NULL );
   1077  1.1  lukem 
   1078  1.1  lukem 							if ( rc != LDAP_SUCCESS ) {
   1079  1.1  lukem 								BER_BVZERO( &(*ap)->a_nvals[i] );
   1080  1.1  lukem 							}
   1081  1.1  lukem 						}
   1082  1.1  lukem 						BER_BVZERO( &(*ap)->a_nvals[i] );
   1083  1.1  lukem 					}
   1084  1.1  lukem 				}
   1085  1.1  lukem 
   1086  1.1  lukem 				/* rewrite the attribute description */
   1087  1.1  lukem 				(*ap)->a_desc = mapping->m_dst_ad;
   1088  1.1  lukem 
   1089  1.1  lukem 				/* will need to check for duplicate attrs */
   1090  1.1  lukem 				check_duplicate_attrs++;
   1091  1.1  lukem 			}
   1092  1.1  lukem 		}
   1093  1.1  lukem 
   1094  1.1  lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
   1095  1.1  lukem 			if ( stripEntryDN ) {
   1096  1.1  lukem 				/* will be generated by frontend */
   1097  1.1  lukem 				goto cleanup_attr;
   1098  1.1  lukem 			}
   1099  1.1  lukem 
   1100  1.1  lukem 		} else if ( !isupdate
   1101  1.1  lukem 			&& !get_relax( op )
   1102  1.1  lukem 			&& (*ap)->a_desc->ad_type->sat_no_user_mod
   1103  1.1  lukem 			&& (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
   1104  1.1  lukem 		{
   1105  1.1  lukem 			goto next_attr;
   1106  1.1  lukem 		}
   1107  1.1  lukem 
   1108  1.1  lukem 		if ( last == -1 ) { /* not yet counted */
   1109  1.1  lukem 			last = (*ap)->a_numvals;
   1110  1.1  lukem 		}
   1111  1.1  lukem 
   1112  1.1  lukem 		if ( last == 0 ) {
   1113  1.1  lukem 			/* empty? leave it in place because of attrsonly and vlv */
   1114  1.1  lukem 			goto next_attr;
   1115  1.1  lukem 		}
   1116  1.1  lukem 		last--;
   1117  1.1  lukem 
   1118  1.1  lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
   1119  1.1  lukem 				|| (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
   1120  1.1  lukem 		{
   1121  1.1  lukem 			struct berval	*bv;
   1122  1.1  lukem 
   1123  1.1  lukem 			for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
   1124  1.1  lukem 				struct berval	mapped;
   1125  1.1  lukem 
   1126  1.1  lukem 				rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
   1127  1.1  lukem 				if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
   1128  1.1  lukem remove_oc:;
   1129  1.1  lukem 					ch_free( bv[0].bv_val );
   1130  1.1  lukem 					BER_BVZERO( &bv[0] );
   1131  1.1  lukem 					if ( &(*ap)->a_vals[last] > &bv[0] ) {
   1132  1.1  lukem 						bv[0] = (*ap)->a_vals[last];
   1133  1.1  lukem 						BER_BVZERO( &(*ap)->a_vals[last] );
   1134  1.1  lukem 					}
   1135  1.1  lukem 					last--;
   1136  1.1  lukem 					bv--;
   1137  1.1  lukem 
   1138  1.1  lukem 				} else if ( mapped.bv_val != bv[0].bv_val ) {
   1139  1.1  lukem 					int	i;
   1140  1.1  lukem 
   1141  1.1  lukem 					for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
   1142  1.1  lukem 						if ( &(*ap)->a_vals[ i ] == bv ) {
   1143  1.1  lukem 							continue;
   1144  1.1  lukem 						}
   1145  1.1  lukem 
   1146  1.1  lukem 						if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
   1147  1.1  lukem 							break;
   1148  1.1  lukem 						}
   1149  1.1  lukem 					}
   1150  1.1  lukem 
   1151  1.1  lukem 					if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
   1152  1.1  lukem 						goto remove_oc;
   1153  1.1  lukem 					}
   1154  1.1  lukem 
   1155  1.1  lukem 					/*
   1156  1.1  lukem 					 * FIXME: after LBER_FREEing
   1157  1.1  lukem 					 * the value is replaced by
   1158  1.1  lukem 					 * ch_alloc'ed memory
   1159  1.1  lukem 					 */
   1160  1.1  lukem 					ber_bvreplace( &bv[0], &mapped );
   1161  1.1  lukem 
   1162  1.1  lukem 					/* FIXME: will need to check
   1163  1.1  lukem 					 * if the structuralObjectClass
   1164  1.1  lukem 					 * changed */
   1165  1.1  lukem 				}
   1166  1.1  lukem 			}
   1167  1.1  lukem 
   1168  1.1  lukem 		/*
   1169  1.1  lukem 		 * It is necessary to try to rewrite attributes with
   1170  1.1  lukem 		 * dn syntax because they might be used in ACLs as
   1171  1.1  lukem 		 * members of groups; since ACLs are applied to the
   1172  1.1  lukem 		 * rewritten stuff, no dn-based subject clause could
   1173  1.1  lukem 		 * be used at the ldap backend side (see
   1174  1.1  lukem 		 * http://www.OpenLDAP.org/faq/data/cache/452.html)
   1175  1.1  lukem 		 * The problem can be overcome by moving the dn-based
   1176  1.1  lukem 		 * ACLs to the target directory server, and letting
   1177  1.1  lukem 		 * everything pass thru the ldap backend. */
   1178  1.1  lukem 		/* FIXME: handle distinguishedName-like syntaxes, like
   1179  1.1  lukem 		 * nameAndOptionalUID */
   1180  1.1  lukem 		} else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
   1181  1.1  lukem 				|| ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
   1182  1.1  lukem 		{
   1183  1.1  lukem 			dc.ctx = "searchAttrDN";
   1184  1.1  lukem 			rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
   1185  1.1  lukem 			if ( rc != LDAP_SUCCESS ) {
   1186  1.1  lukem 				goto cleanup_attr;
   1187  1.1  lukem 			}
   1188  1.1  lukem 
   1189  1.1  lukem 		} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
   1190  1.1  lukem 			dc.ctx = "searchAttrDN";
   1191  1.1  lukem 			rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
   1192  1.1  lukem 			if ( rc != LDAP_SUCCESS ) {
   1193  1.1  lukem 				goto cleanup_attr;
   1194  1.1  lukem 			}
   1195  1.1  lukem 		}
   1196  1.1  lukem 
   1197  1.1  lukem 
   1198  1.1  lukem next_attr:;
   1199  1.1  lukem 		ap = &(*ap)->a_next;
   1200  1.1  lukem 		continue;
   1201  1.1  lukem 
   1202  1.1  lukem cleanup_attr:;
   1203  1.1  lukem 		a = *ap;
   1204  1.1  lukem 		*ap = (*ap)->a_next;
   1205  1.1  lukem 
   1206  1.1  lukem 		attr_free( a );
   1207  1.1  lukem 	}
   1208  1.1  lukem 
   1209  1.1  lukem 	/* only check if some mapping occurred */
   1210  1.1  lukem 	if ( check_duplicate_attrs ) {
   1211  1.1  lukem 		for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
   1212  1.1  lukem 			Attribute	**tap;
   1213  1.1  lukem 
   1214  1.1  lukem 			for ( tap = &(*ap)->a_next; *tap != NULL; ) {
   1215  1.1  lukem 				if ( (*tap)->a_desc == (*ap)->a_desc ) {
   1216  1.1  lukem 					Entry		e = { 0 };
   1217  1.1  lukem 					Modification	mod = { 0 };
   1218  1.1  lukem 					const char	*text = NULL;
   1219  1.1  lukem 					char		textbuf[ SLAP_TEXT_BUFLEN ];
   1220  1.1  lukem 					Attribute	*next = (*tap)->a_next;
   1221  1.1  lukem 
   1222  1.1  lukem 					BER_BVSTR( &e.e_name, "" );
   1223  1.1  lukem 					BER_BVSTR( &e.e_nname, "" );
   1224  1.1  lukem 					e.e_attrs = *ap;
   1225  1.1  lukem 					mod.sm_op = LDAP_MOD_ADD;
   1226  1.1  lukem 					mod.sm_desc = (*ap)->a_desc;
   1227  1.1  lukem 					mod.sm_type = mod.sm_desc->ad_cname;
   1228  1.1  lukem 					mod.sm_numvals = (*tap)->a_numvals;
   1229  1.1  lukem 					mod.sm_values = (*tap)->a_vals;
   1230  1.1  lukem 					if ( (*tap)->a_nvals != (*tap)->a_vals ) {
   1231  1.1  lukem 						mod.sm_nvalues = (*tap)->a_nvals;
   1232  1.1  lukem 					}
   1233  1.1  lukem 
   1234  1.1  lukem 					(void)modify_add_values( &e, &mod,
   1235  1.1  lukem 						/* permissive */ 1,
   1236  1.1  lukem 						&text, textbuf, sizeof( textbuf ) );
   1237  1.1  lukem 
   1238  1.1  lukem 					/* should not insert new attrs! */
   1239  1.1  lukem 					assert( e.e_attrs == *ap );
   1240  1.1  lukem 
   1241  1.1  lukem 					attr_free( *tap );
   1242  1.1  lukem 					*tap = next;
   1243  1.1  lukem 
   1244  1.1  lukem 				} else {
   1245  1.1  lukem 					tap = &(*tap)->a_next;
   1246  1.1  lukem 				}
   1247  1.1  lukem 			}
   1248  1.1  lukem 		}
   1249  1.1  lukem 	}
   1250  1.1  lukem 
   1251  1.1  lukem 	return 0;
   1252  1.1  lukem }
   1253  1.1  lukem 
   1254  1.1  lukem static int
   1255  1.1  lukem rwm_send_entry( Operation *op, SlapReply *rs )
   1256  1.1  lukem {
   1257  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1258  1.1  lukem 	struct ldaprwmap	*rwmap =
   1259  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1260  1.1  lukem 
   1261  1.1  lukem 	Entry			*e = NULL;
   1262  1.1  lukem 	slap_mask_t		flags;
   1263  1.1  lukem 	struct berval		dn = BER_BVNULL,
   1264  1.1  lukem 				ndn = BER_BVNULL;
   1265  1.1  lukem 	dncookie		dc;
   1266  1.1  lukem 	int			rc;
   1267  1.1  lukem 
   1268  1.1  lukem 	assert( rs->sr_entry != NULL );
   1269  1.1  lukem 
   1270  1.1  lukem 	/*
   1271  1.1  lukem 	 * Rewrite the dn of the result, if needed
   1272  1.1  lukem 	 */
   1273  1.1  lukem 	dc.rwmap = rwmap;
   1274  1.1  lukem 	dc.conn = op->o_conn;
   1275  1.1  lukem 	dc.rs = NULL;
   1276  1.1  lukem 	dc.ctx = "searchEntryDN";
   1277  1.1  lukem 
   1278  1.1  lukem 	e = rs->sr_entry;
   1279  1.1  lukem 	flags = rs->sr_flags;
   1280  1.1  lukem 	if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
   1281  1.1  lukem 		/* FIXME: all we need to duplicate are:
   1282  1.1  lukem 		 * - dn
   1283  1.1  lukem 		 * - ndn
   1284  1.1  lukem 		 * - attributes that are requested
   1285  1.1  lukem 		 * - no values if attrsonly is set
   1286  1.1  lukem 		 */
   1287  1.1  lukem 
   1288  1.1  lukem 		e = entry_dup( e );
   1289  1.1  lukem 		if ( e == NULL ) {
   1290  1.1  lukem 			rc = LDAP_NO_MEMORY;
   1291  1.1  lukem 			goto fail;
   1292  1.1  lukem 		}
   1293  1.1  lukem 
   1294  1.1  lukem 		flags &= ~REP_ENTRY_MUSTRELEASE;
   1295  1.1  lukem 		flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
   1296  1.1  lukem 	}
   1297  1.1  lukem 
   1298  1.1  lukem 	/*
   1299  1.1  lukem 	 * Note: this may fail if the target host(s) schema differs
   1300  1.1  lukem 	 * from the one known to the meta, and a DN with unknown
   1301  1.1  lukem 	 * attributes is returned.
   1302  1.1  lukem 	 */
   1303  1.1  lukem 	dn = e->e_name;
   1304  1.1  lukem 	ndn = e->e_nname;
   1305  1.1  lukem 	rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
   1306  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
   1307  1.1  lukem 		rc = 1;
   1308  1.1  lukem 		goto fail;
   1309  1.1  lukem 	}
   1310  1.1  lukem 
   1311  1.1  lukem 	if ( e->e_name.bv_val != dn.bv_val ) {
   1312  1.1  lukem 		ch_free( e->e_name.bv_val );
   1313  1.1  lukem 		ch_free( e->e_nname.bv_val );
   1314  1.1  lukem 
   1315  1.1  lukem 		e->e_name = dn;
   1316  1.1  lukem 		e->e_nname = ndn;
   1317  1.1  lukem 	}
   1318  1.1  lukem 
   1319  1.1  lukem 	/* TODO: map entry attribute types, objectclasses
   1320  1.1  lukem 	 * and dn-valued attribute values */
   1321  1.1  lukem 
   1322  1.1  lukem 	/* FIXME: the entries are in the remote mapping form;
   1323  1.1  lukem 	 * so we need to select those attributes we are willing
   1324  1.1  lukem 	 * to return, and remap them accordingly */
   1325  1.1  lukem 	(void)rwm_attrs( op, rs, &e->e_attrs, 1 );
   1326  1.1  lukem 
   1327  1.1  lukem 	if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
   1328  1.1  lukem 		be_entry_release_rw( op, rs->sr_entry, 0 );
   1329  1.1  lukem 	}
   1330  1.1  lukem 
   1331  1.1  lukem 	rs->sr_entry = e;
   1332  1.1  lukem 	rs->sr_flags = flags;
   1333  1.1  lukem 
   1334  1.1  lukem 	return SLAP_CB_CONTINUE;
   1335  1.1  lukem 
   1336  1.1  lukem fail:;
   1337  1.1  lukem 	if ( e != NULL && e != rs->sr_entry ) {
   1338  1.1  lukem 		if ( e->e_name.bv_val == dn.bv_val ) {
   1339  1.1  lukem 			BER_BVZERO( &e->e_name );
   1340  1.1  lukem 		}
   1341  1.1  lukem 
   1342  1.1  lukem 		if ( e->e_nname.bv_val == ndn.bv_val ) {
   1343  1.1  lukem 			BER_BVZERO( &e->e_nname );
   1344  1.1  lukem 		}
   1345  1.1  lukem 
   1346  1.1  lukem 		entry_free( e );
   1347  1.1  lukem 	}
   1348  1.1  lukem 
   1349  1.1  lukem 	if ( !BER_BVISNULL( &dn ) ) {
   1350  1.1  lukem 		ch_free( dn.bv_val );
   1351  1.1  lukem 	}
   1352  1.1  lukem 
   1353  1.1  lukem 	if ( !BER_BVISNULL( &ndn ) ) {
   1354  1.1  lukem 		ch_free( ndn.bv_val );
   1355  1.1  lukem 	}
   1356  1.1  lukem 
   1357  1.1  lukem 	return rc;
   1358  1.1  lukem }
   1359  1.1  lukem 
   1360  1.1  lukem static int
   1361  1.1  lukem rwm_operational( Operation *op, SlapReply *rs )
   1362  1.1  lukem {
   1363  1.1  lukem 	/* FIXME: the entries are in the remote mapping form;
   1364  1.1  lukem 	 * so we need to select those attributes we are willing
   1365  1.1  lukem 	 * to return, and remap them accordingly */
   1366  1.1  lukem 	if ( rs->sr_operational_attrs ) {
   1367  1.1  lukem 		rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
   1368  1.1  lukem 	}
   1369  1.1  lukem 
   1370  1.1  lukem 	return SLAP_CB_CONTINUE;
   1371  1.1  lukem }
   1372  1.1  lukem 
   1373  1.1  lukem #if 0
   1374  1.1  lukem /* don't use this; it cannot be reverted, and leaves op->o_req_dn
   1375  1.1  lukem  * rewritten for subsequent operations; fine for plain suffixmassage,
   1376  1.1  lukem  * but destroys everything else */
   1377  1.1  lukem static int
   1378  1.1  lukem rwm_chk_referrals( Operation *op, SlapReply *rs )
   1379  1.1  lukem {
   1380  1.1  lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1381  1.1  lukem 	int			rc;
   1382  1.1  lukem 
   1383  1.1  lukem 	rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
   1384  1.1  lukem 	if ( rc != LDAP_SUCCESS ) {
   1385  1.1  lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1386  1.1  lukem 		send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
   1387  1.1  lukem 		return -1;
   1388  1.1  lukem 	}
   1389  1.1  lukem 
   1390  1.1  lukem 	return SLAP_CB_CONTINUE;
   1391  1.1  lukem }
   1392  1.1  lukem #endif
   1393  1.1  lukem 
   1394  1.1  lukem static int
   1395  1.1  lukem rwm_rw_config(
   1396  1.1  lukem 	BackendDB	*be,
   1397  1.1  lukem 	const char	*fname,
   1398  1.1  lukem 	int		lineno,
   1399  1.1  lukem 	int		argc,
   1400  1.1  lukem 	char		**argv )
   1401  1.1  lukem {
   1402  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1403  1.1  lukem 	struct ldaprwmap	*rwmap =
   1404  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1405  1.1  lukem 
   1406  1.1  lukem 	return rewrite_parse( rwmap->rwm_rw,
   1407  1.1  lukem 				fname, lineno, argc, argv );
   1408  1.1  lukem 
   1409  1.1  lukem 	return 0;
   1410  1.1  lukem }
   1411  1.1  lukem 
   1412  1.1  lukem static int
   1413  1.1  lukem rwm_suffixmassage_config(
   1414  1.1  lukem 	BackendDB	*be,
   1415  1.1  lukem 	const char	*fname,
   1416  1.1  lukem 	int		lineno,
   1417  1.1  lukem 	int		argc,
   1418  1.1  lukem 	char		**argv )
   1419  1.1  lukem {
   1420  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1421  1.1  lukem 	struct ldaprwmap	*rwmap =
   1422  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1423  1.1  lukem 
   1424  1.1  lukem 	struct berval		bvnc, nvnc, pvnc, brnc, nrnc, prnc;
   1425  1.1  lukem 	int			massaged;
   1426  1.1  lukem 	int			rc;
   1427  1.1  lukem 
   1428  1.1  lukem 	/*
   1429  1.1  lukem 	 * syntax:
   1430  1.1  lukem 	 *
   1431  1.1  lukem 	 * 	suffixmassage [<suffix>] <massaged suffix>
   1432  1.1  lukem 	 *
   1433  1.1  lukem 	 * the [<suffix>] field must be defined as a valid suffix
   1434  1.1  lukem 	 * for the current database;
   1435  1.1  lukem 	 * the <massaged suffix> shouldn't have already been
   1436  1.1  lukem 	 * defined as a valid suffix for the current server
   1437  1.1  lukem 	 */
   1438  1.1  lukem 	if ( argc == 2 ) {
   1439  1.1  lukem 		if ( be->be_suffix == NULL ) {
   1440  1.1  lukem  			fprintf( stderr, "%s: line %d: "
   1441  1.1  lukem 				       " \"suffixMassage [<suffix>]"
   1442  1.1  lukem 				       " <massaged suffix>\" without "
   1443  1.1  lukem 				       "<suffix> part requires database "
   1444  1.1  lukem 				       "suffix be defined first.\n",
   1445  1.1  lukem 				fname, lineno );
   1446  1.1  lukem 			return 1;
   1447  1.1  lukem 		}
   1448  1.1  lukem 		bvnc = be->be_suffix[ 0 ];
   1449  1.1  lukem 		massaged = 1;
   1450  1.1  lukem 
   1451  1.1  lukem 	} else if ( argc == 3 ) {
   1452  1.1  lukem 		ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
   1453  1.1  lukem 		massaged = 2;
   1454  1.1  lukem 
   1455  1.1  lukem 	} else  {
   1456  1.1  lukem  		fprintf( stderr, "%s: line %d: syntax is"
   1457  1.1  lukem 			       " \"suffixMassage [<suffix>]"
   1458  1.1  lukem 			       " <massaged suffix>\"\n",
   1459  1.1  lukem 			fname, lineno );
   1460  1.1  lukem 		return 1;
   1461  1.1  lukem 	}
   1462  1.1  lukem 
   1463  1.1  lukem 	if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
   1464  1.1  lukem 		fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
   1465  1.1  lukem 			fname, lineno, bvnc.bv_val );
   1466  1.1  lukem 		return 1;
   1467  1.1  lukem 	}
   1468  1.1  lukem 
   1469  1.1  lukem 	ber_str2bv( argv[ massaged ], 0, 0, &brnc );
   1470  1.1  lukem 	if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
   1471  1.1  lukem 		fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
   1472  1.1  lukem 				fname, lineno, brnc.bv_val );
   1473  1.1  lukem 		free( nvnc.bv_val );
   1474  1.1  lukem 		free( pvnc.bv_val );
   1475  1.1  lukem 		return 1;
   1476  1.1  lukem 	}
   1477  1.1  lukem 
   1478  1.1  lukem 	/*
   1479  1.1  lukem 	 * The suffix massaging is emulated
   1480  1.1  lukem 	 * by means of the rewrite capabilities
   1481  1.1  lukem 	 */
   1482  1.1  lukem  	rc = rwm_suffix_massage_config( rwmap->rwm_rw,
   1483  1.1  lukem 			&pvnc, &nvnc, &prnc, &nrnc );
   1484  1.1  lukem 	free( nvnc.bv_val );
   1485  1.1  lukem 	free( pvnc.bv_val );
   1486  1.1  lukem 	free( nrnc.bv_val );
   1487  1.1  lukem 	free( prnc.bv_val );
   1488  1.1  lukem 
   1489  1.1  lukem 	return rc;
   1490  1.1  lukem }
   1491  1.1  lukem 
   1492  1.1  lukem static int
   1493  1.1  lukem rwm_m_config(
   1494  1.1  lukem 	BackendDB	*be,
   1495  1.1  lukem 	const char	*fname,
   1496  1.1  lukem 	int		lineno,
   1497  1.1  lukem 	int		argc,
   1498  1.1  lukem 	char		**argv )
   1499  1.1  lukem {
   1500  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1501  1.1  lukem 	struct ldaprwmap	*rwmap =
   1502  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1503  1.1  lukem 
   1504  1.1  lukem 	/* objectclass/attribute mapping */
   1505  1.1  lukem 	return rwm_map_config( &rwmap->rwm_oc,
   1506  1.1  lukem 			&rwmap->rwm_at,
   1507  1.1  lukem 			fname, lineno, argc, argv );
   1508  1.1  lukem }
   1509  1.1  lukem 
   1510  1.1  lukem static int
   1511  1.1  lukem rwm_response( Operation *op, SlapReply *rs )
   1512  1.1  lukem {
   1513  1.1  lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
   1514  1.1  lukem 	struct ldaprwmap	*rwmap =
   1515  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1516  1.1  lukem 
   1517  1.1  lukem 	int		rc;
   1518  1.1  lukem 
   1519  1.1  lukem 	if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
   1520  1.1  lukem 		return rwm_send_entry( op, rs );
   1521  1.1  lukem 	}
   1522  1.1  lukem 
   1523  1.1  lukem 	switch( op->o_tag ) {
   1524  1.1  lukem 	case LDAP_REQ_SEARCH:
   1525  1.1  lukem 	case LDAP_REQ_BIND:
   1526  1.1  lukem 	case LDAP_REQ_ADD:
   1527  1.1  lukem 	case LDAP_REQ_DELETE:
   1528  1.1  lukem 	case LDAP_REQ_MODRDN:
   1529  1.1  lukem 	case LDAP_REQ_MODIFY:
   1530  1.1  lukem 	case LDAP_REQ_COMPARE:
   1531  1.1  lukem 	case LDAP_REQ_EXTENDED:
   1532  1.1  lukem 		if ( rs->sr_ref ) {
   1533  1.1  lukem 			dncookie		dc;
   1534  1.1  lukem 
   1535  1.1  lukem 			/*
   1536  1.1  lukem 			 * Rewrite the dn of the referrals, if needed
   1537  1.1  lukem 			 */
   1538  1.1  lukem 			dc.rwmap = rwmap;
   1539  1.1  lukem 			dc.conn = op->o_conn;
   1540  1.1  lukem 			dc.rs = NULL;
   1541  1.1  lukem 			dc.ctx = "referralDN";
   1542  1.1  lukem 			rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
   1543  1.1  lukem 			if ( rc != LDAP_SUCCESS ) {
   1544  1.1  lukem 				rc = 1;
   1545  1.1  lukem 				break;
   1546  1.1  lukem 			}
   1547  1.1  lukem 		}
   1548  1.1  lukem 		rc = rwm_matched( op, rs );
   1549  1.1  lukem 		break;
   1550  1.1  lukem 
   1551  1.1  lukem 	default:
   1552  1.1  lukem 		rc = SLAP_CB_CONTINUE;
   1553  1.1  lukem 		break;
   1554  1.1  lukem 	}
   1555  1.1  lukem 
   1556  1.1  lukem 	return rc;
   1557  1.1  lukem }
   1558  1.1  lukem 
   1559  1.1  lukem static int
   1560  1.1  lukem rwm_db_config(
   1561  1.1  lukem 	BackendDB	*be,
   1562  1.1  lukem 	const char	*fname,
   1563  1.1  lukem 	int		lineno,
   1564  1.1  lukem 	int		argc,
   1565  1.1  lukem 	char		**argv )
   1566  1.1  lukem {
   1567  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1568  1.1  lukem 	struct ldaprwmap	*rwmap =
   1569  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1570  1.1  lukem 
   1571  1.1  lukem 	int		rc = 0;
   1572  1.1  lukem 	char		*argv0 = NULL;
   1573  1.1  lukem 
   1574  1.1  lukem 	if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
   1575  1.1  lukem 		argv0 = argv[ 0 ];
   1576  1.1  lukem 		argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
   1577  1.1  lukem 	}
   1578  1.1  lukem 
   1579  1.1  lukem 	if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
   1580  1.1  lukem 		rc = rwm_rw_config( be, fname, lineno, argc, argv );
   1581  1.1  lukem 
   1582  1.1  lukem 	} else if ( strcasecmp( argv[0], "map" ) == 0 ) {
   1583  1.1  lukem 		rc = rwm_m_config( be, fname, lineno, argc, argv );
   1584  1.1  lukem 
   1585  1.1  lukem 	} else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
   1586  1.1  lukem 		rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
   1587  1.1  lukem 
   1588  1.1  lukem 	} else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
   1589  1.1  lukem 		if ( argc != 2 ) {
   1590  1.1  lukem 			fprintf( stderr,
   1591  1.1  lukem 		"%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
   1592  1.1  lukem 					fname, lineno );
   1593  1.1  lukem 			return( 1 );
   1594  1.1  lukem 		}
   1595  1.1  lukem 
   1596  1.1  lukem 		if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
   1597  1.1  lukem 			rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
   1598  1.1  lukem 
   1599  1.1  lukem 		} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
   1600  1.1  lukem 			rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
   1601  1.1  lukem 
   1602  1.1  lukem 		/* TODO: not implemented yet */
   1603  1.1  lukem 		} else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
   1604  1.1  lukem 			fprintf( stderr,
   1605  1.1  lukem 		"%s: line %d: \"discover\" not supported yet "
   1606  1.1  lukem 		"in \"t-f-support {no|yes|discover}\".\n",
   1607  1.1  lukem 					fname, lineno );
   1608  1.1  lukem 			return( 1 );
   1609  1.1  lukem #if 0
   1610  1.1  lukem 			rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
   1611  1.1  lukem #endif
   1612  1.1  lukem 
   1613  1.1  lukem 		} else {
   1614  1.1  lukem 			fprintf( stderr,
   1615  1.1  lukem 	"%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
   1616  1.1  lukem 				fname, lineno, argv[ 1 ] );
   1617  1.1  lukem 			return 1;
   1618  1.1  lukem 		}
   1619  1.1  lukem 
   1620  1.1  lukem 	} else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) ==  0 ) {
   1621  1.1  lukem 		if ( argc !=2 ) {
   1622  1.1  lukem 			fprintf( stderr,
   1623  1.1  lukem 		"%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
   1624  1.1  lukem 					fname, lineno );
   1625  1.1  lukem 			return( 1 );
   1626  1.1  lukem 		}
   1627  1.1  lukem 
   1628  1.1  lukem 		if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
   1629  1.1  lukem 			rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
   1630  1.1  lukem 
   1631  1.1  lukem 		} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
   1632  1.1  lukem 			rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
   1633  1.1  lukem 		}
   1634  1.1  lukem 
   1635  1.1  lukem 	} else {
   1636  1.1  lukem 		rc = SLAP_CONF_UNKNOWN;
   1637  1.1  lukem 	}
   1638  1.1  lukem 
   1639  1.1  lukem 	if ( argv0 ) {
   1640  1.1  lukem 		argv[ 0 ] = argv0;
   1641  1.1  lukem 	}
   1642  1.1  lukem 
   1643  1.1  lukem 	return rc;
   1644  1.1  lukem }
   1645  1.1  lukem 
   1646  1.1  lukem /*
   1647  1.1  lukem  * dynamic configuration...
   1648  1.1  lukem  */
   1649  1.1  lukem 
   1650  1.1  lukem enum {
   1651  1.1  lukem 	/* rewrite */
   1652  1.1  lukem 	RWM_CF_REWRITE = 1,
   1653  1.1  lukem 	RWM_CF_SUFFIXMASSAGE,
   1654  1.1  lukem 
   1655  1.1  lukem 	/* map */
   1656  1.1  lukem 	RWM_CF_MAP,
   1657  1.1  lukem 	RWM_CF_T_F_SUPPORT,
   1658  1.1  lukem 	RWM_CF_NORMALIZE_MAPPED,
   1659  1.1  lukem 
   1660  1.1  lukem 	RWM_CF_LAST
   1661  1.1  lukem };
   1662  1.1  lukem 
   1663  1.1  lukem static slap_verbmasks t_f_mode[] = {
   1664  1.1  lukem 	{ BER_BVC( "yes" ),		RWM_F_SUPPORT_T_F },
   1665  1.1  lukem 	{ BER_BVC( "discover" ),	RWM_F_SUPPORT_T_F_DISCOVER },
   1666  1.1  lukem 	{ BER_BVC( "no" ),		RWM_F_NONE },
   1667  1.1  lukem 	{ BER_BVNULL,			0 }
   1668  1.1  lukem };
   1669  1.1  lukem 
   1670  1.1  lukem static ConfigDriver rwm_cf_gen;
   1671  1.1  lukem 
   1672  1.1  lukem static ConfigTable rwmcfg[] = {
   1673  1.1  lukem 	{ "rwm-rewrite", "rewrite",
   1674  1.1  lukem 		2, 0, STRLENOF("rwm-rewrite"),
   1675  1.1  lukem 		ARG_MAGIC|ARG_QUOTE|RWM_CF_REWRITE, rwm_cf_gen,
   1676  1.1  lukem 		"( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
   1677  1.1  lukem 			"DESC 'Rewrites strings' "
   1678  1.1  lukem 			"EQUALITY caseIgnoreMatch "
   1679  1.1  lukem 			"SYNTAX OMsDirectoryString "
   1680  1.1  lukem 			"X-ORDERED 'VALUES' )",
   1681  1.1  lukem 		NULL, NULL },
   1682  1.1  lukem 
   1683  1.1  lukem 	{ "rwm-suffixmassage", "[virtual]> <real",
   1684  1.1  lukem 		2, 3, 0, ARG_MAGIC|RWM_CF_SUFFIXMASSAGE, rwm_cf_gen,
   1685  1.1  lukem 		NULL, NULL, NULL },
   1686  1.1  lukem 
   1687  1.1  lukem 	{ "rwm-t-f-support", "true|false|discover",
   1688  1.1  lukem 		2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
   1689  1.1  lukem 		"( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
   1690  1.1  lukem 			"DESC 'Absolute filters support' "
   1691  1.1  lukem 			"SYNTAX OMsDirectoryString "
   1692  1.1  lukem 			"SINGLE-VALUE )",
   1693  1.1  lukem 		NULL, NULL },
   1694  1.1  lukem 
   1695  1.1  lukem 	{ "rwm-map", "{objectClass|attribute}",
   1696  1.1  lukem 		2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
   1697  1.1  lukem 		"( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
   1698  1.1  lukem 			"DESC 'maps attributes/objectClasses' "
   1699  1.1  lukem 			"SYNTAX OMsDirectoryString "
   1700  1.1  lukem 			"X-ORDERED 'VALUES' )",
   1701  1.1  lukem 		NULL, NULL },
   1702  1.1  lukem 
   1703  1.1  lukem 	{ "rwm-normalize-mapped-attrs", "true|false",
   1704  1.1  lukem 		2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
   1705  1.1  lukem 		"( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
   1706  1.1  lukem 			"DESC 'Normalize mapped attributes/objectClasses' "
   1707  1.1  lukem 			"SYNTAX OMsBoolean "
   1708  1.1  lukem 			"SINGLE-VALUE )",
   1709  1.1  lukem 		NULL, NULL },
   1710  1.1  lukem 
   1711  1.1  lukem 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
   1712  1.1  lukem };
   1713  1.1  lukem 
   1714  1.1  lukem static ConfigOCs rwmocs[] = {
   1715  1.1  lukem 	{ "( OLcfgOvOc:16.1 "
   1716  1.1  lukem 		"NAME 'olcRwmConfig' "
   1717  1.1  lukem 		"DESC 'Rewrite/remap configuration' "
   1718  1.1  lukem 		"SUP olcOverlayConfig "
   1719  1.1  lukem 		"MAY ( "
   1720  1.1  lukem 			"olcRwmRewrite $ "
   1721  1.1  lukem 			"olcRwmTFSupport $ "
   1722  1.1  lukem 			"olcRwmMap $ "
   1723  1.1  lukem 			"olcRwmNormalizeMapped "
   1724  1.1  lukem 			") )",
   1725  1.1  lukem 		Cft_Overlay, rwmcfg, NULL, NULL },
   1726  1.1  lukem 	{ NULL, 0, NULL }
   1727  1.1  lukem };
   1728  1.1  lukem 
   1729  1.1  lukem static void
   1730  1.1  lukem slap_rewrite_unparse( BerVarray in, BerVarray *out )
   1731  1.1  lukem {
   1732  1.1  lukem 	int		i;
   1733  1.1  lukem 	BerVarray	bva = NULL;
   1734  1.1  lukem 	char		ibuf[32], *ptr;
   1735  1.1  lukem 	struct berval	idx;
   1736  1.1  lukem 
   1737  1.1  lukem 	assert( in != NULL );
   1738  1.1  lukem 
   1739  1.1  lukem 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
   1740  1.1  lukem 		/* count'em */ ;
   1741  1.1  lukem 
   1742  1.1  lukem 	if ( i == 0 ) {
   1743  1.1  lukem 		return;
   1744  1.1  lukem 	}
   1745  1.1  lukem 
   1746  1.1  lukem 	idx.bv_val = ibuf;
   1747  1.1  lukem 
   1748  1.1  lukem 	bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
   1749  1.1  lukem 	BER_BVZERO( &bva[ 0 ] );
   1750  1.1  lukem 
   1751  1.1  lukem 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
   1752  1.1  lukem 		idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
   1753  1.1  lukem 		if ( idx.bv_len >= sizeof( ibuf ) ) {
   1754  1.1  lukem 			ber_bvarray_free( bva );
   1755  1.1  lukem 			return;
   1756  1.1  lukem 		}
   1757  1.1  lukem 
   1758  1.1  lukem 		bva[i].bv_len = idx.bv_len + in[i].bv_len;
   1759  1.1  lukem 		bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
   1760  1.1  lukem 		ptr = lutil_strcopy( bva[i].bv_val, ibuf );
   1761  1.1  lukem 		ptr = lutil_strcopy( ptr, in[i].bv_val );
   1762  1.1  lukem 		*ptr = '\0';
   1763  1.1  lukem 		BER_BVZERO( &bva[ i + 1 ] );
   1764  1.1  lukem 	}
   1765  1.1  lukem 
   1766  1.1  lukem 	*out = bva;
   1767  1.1  lukem }
   1768  1.1  lukem 
   1769  1.1  lukem static int
   1770  1.1  lukem rwm_cf_gen( ConfigArgs *c )
   1771  1.1  lukem {
   1772  1.1  lukem 	slap_overinst		*on = (slap_overinst *)c->bi;
   1773  1.1  lukem 	struct ldaprwmap	*rwmap =
   1774  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1775  1.1  lukem 
   1776  1.1  lukem 	BackendDB		db;
   1777  1.1  lukem 	char			*argv0;
   1778  1.1  lukem 	int			rc = 0;
   1779  1.1  lukem 
   1780  1.1  lukem 	db = *c->be;
   1781  1.1  lukem 	db.bd_info = c->bi;
   1782  1.1  lukem 
   1783  1.1  lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
   1784  1.1  lukem 		struct berval	bv = BER_BVNULL;
   1785  1.1  lukem 
   1786  1.1  lukem 		switch ( c->type ) {
   1787  1.1  lukem 		case RWM_CF_REWRITE:
   1788  1.1  lukem 			if ( rwmap->rwm_bva_rewrite == NULL ) {
   1789  1.1  lukem 				rc = 1;
   1790  1.1  lukem 
   1791  1.1  lukem 			} else {
   1792  1.1  lukem 				slap_rewrite_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
   1793  1.1  lukem 				if ( !c->rvalue_vals ) {
   1794  1.1  lukem 					rc = 1;
   1795  1.1  lukem 				}
   1796  1.1  lukem 			}
   1797  1.1  lukem 			break;
   1798  1.1  lukem 
   1799  1.1  lukem 		case RWM_CF_T_F_SUPPORT:
   1800  1.1  lukem 			enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
   1801  1.1  lukem 			if ( BER_BVISNULL( &bv ) ) {
   1802  1.1  lukem 				/* there's something wrong... */
   1803  1.1  lukem 				assert( 0 );
   1804  1.1  lukem 				rc = 1;
   1805  1.1  lukem 
   1806  1.1  lukem 			} else {
   1807  1.1  lukem 				value_add_one( &c->rvalue_vals, &bv );
   1808  1.1  lukem 			}
   1809  1.1  lukem 			break;
   1810  1.1  lukem 
   1811  1.1  lukem 		case RWM_CF_MAP:
   1812  1.1  lukem 			if ( rwmap->rwm_bva_map == NULL ) {
   1813  1.1  lukem 				rc = 1;
   1814  1.1  lukem 
   1815  1.1  lukem 			} else {
   1816  1.1  lukem 				value_add( &c->rvalue_vals, rwmap->rwm_bva_map );
   1817  1.1  lukem 			}
   1818  1.1  lukem 			break;
   1819  1.1  lukem 
   1820  1.1  lukem 		case RWM_CF_NORMALIZE_MAPPED:
   1821  1.1  lukem 			c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
   1822  1.1  lukem 			break;
   1823  1.1  lukem 
   1824  1.1  lukem 		default:
   1825  1.1  lukem 			assert( 0 );
   1826  1.1  lukem 			rc = 1;
   1827  1.1  lukem 		}
   1828  1.1  lukem 
   1829  1.1  lukem 		return rc;
   1830  1.1  lukem 
   1831  1.1  lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   1832  1.1  lukem 		switch ( c->type ) {
   1833  1.1  lukem 		case RWM_CF_REWRITE:
   1834  1.1  lukem 			if ( c->valx >= 0 ) {
   1835  1.1  lukem 				/* single modification is not allowed */
   1836  1.1  lukem 				rc = 1;
   1837  1.1  lukem 
   1838  1.1  lukem 			} else if ( rwmap->rwm_rw != NULL ) {
   1839  1.1  lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   1840  1.1  lukem 				assert( rwmap->rwm_rw == NULL );
   1841  1.1  lukem 
   1842  1.1  lukem 				ber_bvarray_free( rwmap->rwm_bva_rewrite );
   1843  1.1  lukem 				rwmap->rwm_bva_rewrite = NULL;
   1844  1.1  lukem 			}
   1845  1.1  lukem 			break;
   1846  1.1  lukem 
   1847  1.1  lukem 		case RWM_CF_T_F_SUPPORT:
   1848  1.1  lukem 			rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
   1849  1.1  lukem 			break;
   1850  1.1  lukem 
   1851  1.1  lukem 		case RWM_CF_MAP:
   1852  1.1  lukem 			if ( c->valx >= 0 ) {
   1853  1.1  lukem 				/* single modification is not allowed */
   1854  1.1  lukem 				rc = 1;
   1855  1.1  lukem 
   1856  1.1  lukem 			} else {
   1857  1.1  lukem 				avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   1858  1.1  lukem 				avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   1859  1.1  lukem 				avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   1860  1.1  lukem 				avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   1861  1.1  lukem 
   1862  1.1  lukem 				rwmap->rwm_oc.remap = NULL;
   1863  1.1  lukem 				rwmap->rwm_oc.map = NULL;
   1864  1.1  lukem 				rwmap->rwm_at.remap = NULL;
   1865  1.1  lukem 				rwmap->rwm_at.map = NULL;
   1866  1.1  lukem 
   1867  1.1  lukem 				ber_bvarray_free( rwmap->rwm_bva_map );
   1868  1.1  lukem 				rwmap->rwm_bva_map = NULL;
   1869  1.1  lukem 			}
   1870  1.1  lukem 			break;
   1871  1.1  lukem 
   1872  1.1  lukem 		case RWM_CF_NORMALIZE_MAPPED:
   1873  1.1  lukem 			rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
   1874  1.1  lukem 			break;
   1875  1.1  lukem 
   1876  1.1  lukem 		default:
   1877  1.1  lukem 			return 1;
   1878  1.1  lukem 		}
   1879  1.1  lukem 		return rc;
   1880  1.1  lukem 	}
   1881  1.1  lukem 
   1882  1.1  lukem 	switch ( c->type ) {
   1883  1.1  lukem 	case RWM_CF_REWRITE:
   1884  1.1  lukem 		argv0 = c->argv[ 0 ];
   1885  1.1  lukem 		c->argv[ 0 ] += STRLENOF( "rwm-" );
   1886  1.1  lukem 		rc = rwm_rw_config( &db, c->fname, c->lineno, c->argc, c->argv );
   1887  1.1  lukem 		c->argv[ 0 ] = argv0;
   1888  1.1  lukem 		if ( rc ) {
   1889  1.1  lukem 			return 1;
   1890  1.1  lukem 
   1891  1.1  lukem 		} else {
   1892  1.1  lukem 			char		*line;
   1893  1.1  lukem 			struct berval	bv;
   1894  1.1  lukem 
   1895  1.1  lukem 			line = ldap_charray2str( c->argv, "\" \"" );
   1896  1.1  lukem 			if ( line != NULL ) {
   1897  1.1  lukem 				int	len = strlen( c->argv[ 0 ] );
   1898  1.1  lukem 
   1899  1.1  lukem 				ber_str2bv( line, 0, 0, &bv );
   1900  1.1  lukem 				AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
   1901  1.1  lukem 					bv.bv_len - ( len + 1 ) );
   1902  1.1  lukem 				bv.bv_val[ bv.bv_len - 1 ] = '"';
   1903  1.1  lukem 				ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
   1904  1.1  lukem 			}
   1905  1.1  lukem 		}
   1906  1.1  lukem 		break;
   1907  1.1  lukem 
   1908  1.1  lukem 	case RWM_CF_SUFFIXMASSAGE:
   1909  1.1  lukem 		argv0 = c->argv[ 0 ];
   1910  1.1  lukem 		c->argv[ 0 ] += STRLENOF( "rwm-" );
   1911  1.1  lukem 		rc = rwm_suffixmassage_config( &db, c->fname, c->lineno, c->argc, c->argv );
   1912  1.1  lukem 		c->argv[ 0 ] = argv0;
   1913  1.1  lukem 		if ( rc ) {
   1914  1.1  lukem 			return 1;
   1915  1.1  lukem 
   1916  1.1  lukem 		} else {
   1917  1.1  lukem 			char		*line;
   1918  1.1  lukem 			struct berval	bv;
   1919  1.1  lukem 
   1920  1.1  lukem 			/* FIXME: not optimal; in fact, this keeps track
   1921  1.1  lukem 			 * of the fact that a set of rules was added
   1922  1.1  lukem 			 * using the rwm-suffixmassage shortcut, but the
   1923  1.1  lukem 			 * rules are not clarified */
   1924  1.1  lukem 
   1925  1.1  lukem 			line = ldap_charray2str( c->argv, "\" \"" );
   1926  1.1  lukem 			if ( line != NULL ) {
   1927  1.1  lukem 				int	len = strlen( c->argv[ 0 ] );
   1928  1.1  lukem 
   1929  1.1  lukem 				ber_str2bv( line, 0, 0, &bv );
   1930  1.1  lukem 				AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
   1931  1.1  lukem 					bv.bv_len - ( len + 1 ) );
   1932  1.1  lukem 				bv.bv_val[ bv.bv_len - 1 ] = '"';
   1933  1.1  lukem 				ber_bvarray_add( &rwmap->rwm_bva_rewrite, &bv );
   1934  1.1  lukem 			}
   1935  1.1  lukem 		}
   1936  1.1  lukem 		break;
   1937  1.1  lukem 
   1938  1.1  lukem 	case RWM_CF_T_F_SUPPORT:
   1939  1.1  lukem 		rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
   1940  1.1  lukem 		if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
   1941  1.1  lukem 			return 1;
   1942  1.1  lukem 		}
   1943  1.1  lukem 
   1944  1.1  lukem 		rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
   1945  1.1  lukem 		rwmap->rwm_flags |= t_f_mode[ rc ].mask;
   1946  1.1  lukem 		rc = 0;
   1947  1.1  lukem 		break;
   1948  1.1  lukem 
   1949  1.1  lukem 	case RWM_CF_MAP:
   1950  1.1  lukem 		argv0 = c->argv[ 0 ];
   1951  1.1  lukem 		c->argv[ 0 ] += STRLENOF( "rwm-" );
   1952  1.1  lukem 		rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
   1953  1.1  lukem 		c->argv[ 0 ] = argv0;
   1954  1.1  lukem 		if ( rc ) {
   1955  1.1  lukem 			return 1;
   1956  1.1  lukem 
   1957  1.1  lukem 		} else {
   1958  1.1  lukem 			char		*line;
   1959  1.1  lukem 			struct berval	bv;
   1960  1.1  lukem 
   1961  1.1  lukem 			line = ldap_charray2str( &c->argv[ 1 ], " " );
   1962  1.1  lukem 			if ( line != NULL ) {
   1963  1.1  lukem 				ber_str2bv( line, 0, 0, &bv );
   1964  1.1  lukem 				ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
   1965  1.1  lukem 			}
   1966  1.1  lukem 		}
   1967  1.1  lukem 		break;
   1968  1.1  lukem 
   1969  1.1  lukem 	case RWM_CF_NORMALIZE_MAPPED:
   1970  1.1  lukem 		if ( c->value_int ) {
   1971  1.1  lukem 			rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
   1972  1.1  lukem 		} else {
   1973  1.1  lukem 			rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
   1974  1.1  lukem 		}
   1975  1.1  lukem 		break;
   1976  1.1  lukem 
   1977  1.1  lukem 	default:
   1978  1.1  lukem 		assert( 0 );
   1979  1.1  lukem 		return 1;
   1980  1.1  lukem 	}
   1981  1.1  lukem 
   1982  1.1  lukem 	return rc;
   1983  1.1  lukem }
   1984  1.1  lukem 
   1985  1.1  lukem static int
   1986  1.1  lukem rwm_db_init(
   1987  1.1  lukem 	BackendDB	*be,
   1988  1.1  lukem 	ConfigReply	*cr )
   1989  1.1  lukem {
   1990  1.1  lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1991  1.1  lukem 	struct ldaprwmap	*rwmap;
   1992  1.1  lukem 	char			*rargv[ 3 ];
   1993  1.1  lukem 	int			rc = 0;
   1994  1.1  lukem 
   1995  1.1  lukem 	rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
   1996  1.1  lukem 
   1997  1.1  lukem  	rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
   1998  1.1  lukem 	if ( rwmap->rwm_rw == NULL ) {
   1999  1.1  lukem  		rc = -1;
   2000  1.1  lukem 		goto error_return;
   2001  1.1  lukem  	}
   2002  1.1  lukem 
   2003  1.1  lukem 	/* this rewriteContext by default must be null;
   2004  1.1  lukem 	 * rules can be added if required */
   2005  1.1  lukem 	rargv[ 0 ] = "rewriteContext";
   2006  1.1  lukem 	rargv[ 1 ] = "searchFilter";
   2007  1.1  lukem 	rargv[ 2 ] = NULL;
   2008  1.1  lukem 	rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 1, 2, rargv );
   2009  1.1  lukem 
   2010  1.1  lukem 	rargv[ 0 ] = "rewriteContext";
   2011  1.1  lukem 	rargv[ 1 ] = "default";
   2012  1.1  lukem 	rargv[ 2 ] = NULL;
   2013  1.1  lukem 	rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
   2014  1.1  lukem 
   2015  1.1  lukem error_return:;
   2016  1.1  lukem 	on->on_bi.bi_private = (void *)rwmap;
   2017  1.1  lukem 
   2018  1.1  lukem 	if ( rc ) {
   2019  1.1  lukem 		(void)rwm_db_destroy( be, NULL );
   2020  1.1  lukem 	}
   2021  1.1  lukem 
   2022  1.1  lukem 	return rc;
   2023  1.1  lukem }
   2024  1.1  lukem 
   2025  1.1  lukem static int
   2026  1.1  lukem rwm_db_destroy(
   2027  1.1  lukem 	BackendDB	*be,
   2028  1.1  lukem 	ConfigReply	*cr )
   2029  1.1  lukem {
   2030  1.1  lukem 	slap_overinst	*on = (slap_overinst *) be->bd_info;
   2031  1.1  lukem 	int		rc = 0;
   2032  1.1  lukem 
   2033  1.1  lukem 	if ( on->on_bi.bi_private ) {
   2034  1.1  lukem 		struct ldaprwmap	*rwmap =
   2035  1.1  lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   2036  1.1  lukem 
   2037  1.1  lukem 		if ( rwmap->rwm_rw ) {
   2038  1.1  lukem 			rewrite_info_delete( &rwmap->rwm_rw );
   2039  1.1  lukem 			ber_bvarray_free( rwmap->rwm_bva_rewrite );
   2040  1.1  lukem 		}
   2041  1.1  lukem 
   2042  1.1  lukem 		avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2043  1.1  lukem 		avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2044  1.1  lukem 		avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2045  1.1  lukem 		avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2046  1.1  lukem 		ber_bvarray_free( rwmap->rwm_bva_map );
   2047  1.1  lukem 
   2048  1.1  lukem 		ch_free( rwmap );
   2049  1.1  lukem 	}
   2050  1.1  lukem 
   2051  1.1  lukem 	return rc;
   2052  1.1  lukem }
   2053  1.1  lukem 
   2054  1.1  lukem static slap_overinst rwm = { { NULL } };
   2055  1.1  lukem 
   2056  1.1  lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
   2057  1.1  lukem static
   2058  1.1  lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
   2059  1.1  lukem int
   2060  1.1  lukem rwm_initialize( void )
   2061  1.1  lukem {
   2062  1.1  lukem 	int		rc;
   2063  1.1  lukem 
   2064  1.1  lukem 	/* Make sure we don't exceed the bits reserved for userland */
   2065  1.1  lukem 	config_check_userland( RWM_CF_LAST );
   2066  1.1  lukem 
   2067  1.1  lukem 	memset( &rwm, 0, sizeof( slap_overinst ) );
   2068  1.1  lukem 
   2069  1.1  lukem 	rwm.on_bi.bi_type = "rwm";
   2070  1.1  lukem 	rwm.on_bi.bi_flags =
   2071  1.1  lukem 		SLAPO_BFLAG_SINGLE |
   2072  1.1  lukem 		0;
   2073  1.1  lukem 
   2074  1.1  lukem 	rwm.on_bi.bi_db_init = rwm_db_init;
   2075  1.1  lukem 	rwm.on_bi.bi_db_config = rwm_db_config;
   2076  1.1  lukem 	rwm.on_bi.bi_db_destroy = rwm_db_destroy;
   2077  1.1  lukem 
   2078  1.1  lukem 	rwm.on_bi.bi_op_bind = rwm_op_bind;
   2079  1.1  lukem 	rwm.on_bi.bi_op_search = rwm_op_search;
   2080  1.1  lukem 	rwm.on_bi.bi_op_compare = rwm_op_compare;
   2081  1.1  lukem 	rwm.on_bi.bi_op_modify = rwm_op_modify;
   2082  1.1  lukem 	rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
   2083  1.1  lukem 	rwm.on_bi.bi_op_add = rwm_op_add;
   2084  1.1  lukem 	rwm.on_bi.bi_op_delete = rwm_op_delete;
   2085  1.1  lukem 	rwm.on_bi.bi_op_unbind = rwm_op_unbind;
   2086  1.1  lukem 	rwm.on_bi.bi_extended = rwm_extended;
   2087  1.1  lukem 
   2088  1.1  lukem 	rwm.on_bi.bi_operational = rwm_operational;
   2089  1.1  lukem 	rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
   2090  1.1  lukem 
   2091  1.1  lukem 	rwm.on_bi.bi_connection_init = rwm_conn_init;
   2092  1.1  lukem 	rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
   2093  1.1  lukem 
   2094  1.1  lukem 	rwm.on_response = rwm_response;
   2095  1.1  lukem 
   2096  1.1  lukem 	rwm.on_bi.bi_cf_ocs = rwmocs;
   2097  1.1  lukem 
   2098  1.1  lukem 	rc = config_register_schema( rwmcfg, rwmocs );
   2099  1.1  lukem 	if ( rc ) {
   2100  1.1  lukem 		return rc;
   2101  1.1  lukem 	}
   2102  1.1  lukem 
   2103  1.1  lukem 	return overlay_register( &rwm );
   2104  1.1  lukem }
   2105  1.1  lukem 
   2106  1.1  lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
   2107  1.1  lukem int
   2108  1.1  lukem init_module( int argc, char *argv[] )
   2109  1.1  lukem {
   2110  1.1  lukem 	return rwm_initialize();
   2111  1.1  lukem }
   2112  1.1  lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
   2113  1.1  lukem 
   2114  1.1  lukem #endif /* SLAPD_OVER_RWM */
   2115