rwm.c 57.4 KB
Newer Older
1
/* rwm.c - rewrite/remap operations */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
3
4
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
5
 * Copyright 2003-2009 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
 * Portions Copyright 2003 Pierangelo Masarati.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
16
17
18
19
 */

#include "portable.h"

20
21
#ifdef SLAPD_OVER_RWM

22
23
#include <stdio.h>

24
25
#include <ac/string.h>

26
#include "slap.h"
27
28
#include "config.h"
#include "lutil.h"
29
30
#include "rwm.h"

31
typedef struct rwm_op_state {
Howard Chu's avatar
Howard Chu committed
32
	ber_tag_t r_tag;
33
34
35
36
	struct berval ro_dn;
	struct berval ro_ndn;
	struct berval r_dn;
	struct berval r_ndn;
37
	AttributeName *mapped_attrs;
38
39
40
41
42
43
44
45
	OpRequest o_request;
} rwm_op_state;

typedef struct rwm_op_cb {
	slap_callback cb;
	rwm_op_state ros;
} rwm_op_cb;

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
46
47
48
49
50
51
static int
rwm_db_destroy( BackendDB *be, ConfigReply *cr );

static int
rwm_send_entry( Operation *op, SlapReply *rs );

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
52
53
static void
rwm_op_rollback( Operation *op, SlapReply *rs, rwm_op_state *ros )
54
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
55
	if ( !BER_BVISNULL( &ros->ro_dn ) ) {
56
		op->o_req_dn = ros->ro_dn;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
57
58
	}
	if ( !BER_BVISNULL( &ros->ro_ndn ) ) {
59
		op->o_req_ndn = ros->ro_ndn;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
60
	}
61

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
62
63
64
65
66
67
68
	if ( !BER_BVISNULL( &ros->r_dn )
		&& ros->r_dn.bv_val != ros->ro_dn.bv_val )
	{
		assert( ros->r_dn.bv_val != ros->r_ndn.bv_val );
		ch_free( ros->r_dn.bv_val );
		BER_BVZERO( &ros->r_dn );
	}
69

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
70
71
72
73
74
75
	if ( !BER_BVISNULL( &ros->r_ndn )
		&& ros->r_ndn.bv_val != ros->ro_ndn.bv_val )
	{
		ch_free( ros->r_ndn.bv_val );
		BER_BVZERO( &ros->r_ndn );
	}
76

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
	BER_BVZERO( &ros->ro_dn );
	BER_BVZERO( &ros->ro_ndn );

	switch( ros->r_tag ) {
	case LDAP_REQ_COMPARE:
		if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
			op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
		op->orc_ava = ros->orc_ava;
		break;
	case LDAP_REQ_MODIFY:
		slap_mods_free( op->orm_modlist, 1 );
		op->orm_modlist = ros->orm_modlist;
		break;
	case LDAP_REQ_MODRDN:
		if ( op->orr_newSup != ros->orr_newSup ) {
			ch_free( op->orr_newSup->bv_val );
			ch_free( op->orr_nnewSup->bv_val );
			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
			op->orr_newSup = ros->orr_newSup;
			op->orr_nnewSup = ros->orr_nnewSup;
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
99
100
101
102
103
104
		if ( op->orr_newrdn.bv_val != ros->orr_newrdn.bv_val ) {
			ch_free( op->orr_newrdn.bv_val );
			ch_free( op->orr_nnewrdn.bv_val );
			op->orr_newrdn = ros->orr_newrdn;
			op->orr_nnewrdn = ros->orr_nnewrdn;
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
105
106
107
		break;
	case LDAP_REQ_SEARCH:
		ch_free( ros->mapped_attrs );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
108
		filter_free_x( op, op->ors_filter, 1 );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
109
110
111
112
113
114
115
116
117
118
119
120
121
		ch_free( op->ors_filterstr.bv_val );
		op->ors_attrs = ros->ors_attrs;
		op->ors_filter = ros->ors_filter;
		op->ors_filterstr = ros->ors_filterstr;
		break;
	case LDAP_REQ_EXTENDED:
		if ( op->ore_reqdata != ros->ore_reqdata ) {
			ber_bvfree( op->ore_reqdata );
			op->ore_reqdata = ros->ore_reqdata;
		}
		break;
	case LDAP_REQ_BIND:
		if ( rs->sr_err == LDAP_SUCCESS ) {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
122
#if 0
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
123
124
125
126
127
128
129
130
			ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
			/* too late, c_mutex released */
			fprintf( stderr, "*** DN: \"%s\" => \"%s\"\n",
				op->o_conn->c_ndn.bv_val,
				op->o_req_ndn.bv_val );
			ber_bvreplace( &op->o_conn->c_ndn,
				&op->o_req_ndn );
			ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
131
#endif
132
		}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
		break;
	default:	break;
	}
}

static int
rwm_op_cleanup( Operation *op, SlapReply *rs )
{
	slap_callback	*cb = op->o_callback;
	rwm_op_state *ros = cb->sc_private;

	if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
		op->o_abandon || rs->sr_err == SLAPD_ABANDON )
	{
		rwm_op_rollback( op, rs, ros );

Howard Chu's avatar
Howard Chu committed
149
150
		op->o_callback = op->o_callback->sc_next;
		op->o_tmpfree( cb, op->o_tmpmemctx );
151
152
153
154
155
156
157
158
159
160
	}

	return SLAP_CB_CONTINUE;
}

static rwm_op_cb *
rwm_callback_get( Operation *op, SlapReply *rs )
{
	rwm_op_cb	*roc = NULL;

Howard Chu's avatar
Howard Chu committed
161
	roc = op->o_tmpalloc( sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
162
163
164
165
	roc->cb.sc_cleanup = rwm_op_cleanup;
	roc->cb.sc_response = NULL;
	roc->cb.sc_next = op->o_callback;
	roc->cb.sc_private = &roc->ros;
Howard Chu's avatar
Howard Chu committed
166
	roc->ros.r_tag = op->o_tag;
167
168
169
170
171
172
173
174
175
176
177
178
179
	roc->ros.ro_dn = op->o_req_dn;
	roc->ros.ro_ndn = op->o_req_ndn;
	roc->ros.o_request = op->o_request;
	BER_BVZERO( &roc->ros.r_dn );
	BER_BVZERO( &roc->ros.r_ndn );

	return roc;
}


static int
rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
	rwm_op_state *ros )
180
181
182
183
184
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
185
186
	struct berval		dn = BER_BVNULL,
				ndn = BER_BVNULL;
187
188
189
190
	int			rc = 0;
	dncookie		dc;

	/*
191
	 * Rewrite the dn if needed
192
193
194
195
196
197
	 */
	dc.rwmap = rwmap;
	dc.conn = op->o_conn;
	dc.rs = rs;
	dc.ctx = (char *)cookie;

198
199
200
201
	/* NOTE: in those cases where only the ndn is available,
	 * and the caller sets op->o_req_dn = op->o_req_ndn,
	 * only rewrite the op->o_req_ndn and use it as 
	 * op->o_req_dn as well */
202
	ndn = op->o_req_ndn;
203
	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
204
205
206
207
		dn = op->o_req_dn;
		rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
	} else {
		rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
208
209
	}

210
211
212
213
	if ( rc != LDAP_SUCCESS ) {
		return rc;
	}

214
215
216
	if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
			|| ndn.bv_val == op->o_req_ndn.bv_val )
	{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
217
218
219
		return LDAP_SUCCESS;
	}

220
	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
221
		op->o_req_dn = dn;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
222
		assert( BER_BVISNULL( &ros->r_dn ) );
223
		ros->r_dn = dn;
224
225
226
	} else {
		op->o_req_dn = ndn;
	}
227
	op->o_req_ndn = ndn;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
228
	assert( BER_BVISNULL( &ros->r_ndn ) );
229
	ros->r_ndn = ndn;
230
231
232
233
234

	return LDAP_SUCCESS;
}

static int
235
rwm_op_add( Operation *op, SlapReply *rs )
236
{
237
238
239
240
241
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	int			rc,
242
				i;
243
	Attribute		**ap = NULL;
244
	char			*olddn = op->o_req_dn.bv_val;
245
	int			isupdate;
246

247
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
248
249

	rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
250
	if ( rc != LDAP_SUCCESS ) {
251
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
252
		send_ldap_error( op, rs, rc, "addDN massage error" );
253
254
255
		return -1;
	}

256
	if ( olddn != op->o_req_dn.bv_val ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
257
258
		ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
		ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
259
260
	}

261
	/* Count number of attributes in entry */ 
262
	isupdate = be_shadow_update( op );
263
264
265
	for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
		Attribute	*a;

266
267
268
269
270
		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
				(*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
		{
			int		j, last;

271
			last = (*ap)->a_numvals - 1;
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
			for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
				struct ldapmapping	*mapping = NULL;

				( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
						&mapping, RWM_MAP );
				if ( mapping == NULL ) {
					if ( rwmap->rwm_at.drop_missing ) {
						/* FIXME: we allow to remove objectClasses as well;
						 * if the resulting entry is inconsistent, that's
						 * the relayed database's business...
						 */
						ch_free( (*ap)->a_vals[ j ].bv_val );
						if ( last > j ) {
							(*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
						}
						BER_BVZERO( &(*ap)->a_vals[ last ] );
288
						(*ap)->a_numvals--;
289
290
291
292
293
294
295
296
297
298
						last--;
						j--;
					}

				} else {
					ch_free( (*ap)->a_vals[ j ].bv_val );
					ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
				}
			}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
299
		} else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
300
		{
301
			goto next_attr;
302

303
304
		} else {
			struct ldapmapping	*mapping = NULL;
305

306
307
308
309
310
311
312
313
			( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
					&mapping, RWM_MAP );
			if ( mapping == NULL ) {
				if ( rwmap->rwm_at.drop_missing ) {
					goto cleanup_attr;
				}
			}

314
315
			if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
					|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
316
317
318
319
320
321
322
323
324
325
326
			{
				/*
				 * FIXME: rewrite could fail; in this case
				 * the operation should give up, right?
				 */
				rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
						(*ap)->a_vals,
						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
				if ( rc ) {
					goto cleanup_attr;
				}
327

328
329
330
331
332
333
334
			} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
				rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
						(*ap)->a_vals,
						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
				if ( rc != LDAP_SUCCESS ) {
					goto cleanup_attr;
				}
335
			}
336
337
		
			if ( mapping != NULL ) {
338
				assert( mapping->m_dst_ad != NULL );
339
340
				(*ap)->a_desc = mapping->m_dst_ad;
			}
341
342
		}

343
next_attr:;
344
345
346
347
348
349
350
351
		ap = &(*ap)->a_next;
		continue;

cleanup_attr:;
		/* FIXME: leaking attribute/values? */
		a = *ap;

		*ap = (*ap)->a_next;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
352
		attr_free( a );
353
354
	}

355
356
	op->o_callback = &roc->cb;

357
358
359
	return SLAP_CB_CONTINUE;
}

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
static int
rwm_conn_init( BackendDB *be, Connection *conn )
{
	slap_overinst		*on = (slap_overinst *) be->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	( void )rewrite_session_init( rwmap->rwm_rw, conn );

	return SLAP_CB_CONTINUE;
}

static int
rwm_conn_destroy( BackendDB *be, Connection *conn )
{
	slap_overinst		*on = (slap_overinst *) be->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	( void )rewrite_session_delete( rwmap->rwm_rw, conn );

	return SLAP_CB_CONTINUE;
}

384
static int
385
rwm_op_bind( Operation *op, SlapReply *rs )
386
{
387
388
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	int			rc;
389

390
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
391
392

	rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
393
	if ( rc != LDAP_SUCCESS ) {
394
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
395
		send_ldap_error( op, rs, rc, "bindDN massage error" );
396
		return -1;
397
398
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
399
	overlay_callback_after_backover( op, &roc->cb, 1 );
400

401
402
403
	return SLAP_CB_CONTINUE;
}

404
static int
405
rwm_op_unbind( Operation *op, SlapReply *rs )
406
407
408
409
410
411
412
413
414
415
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	rewrite_session_delete( rwmap->rwm_rw, op->o_conn );

	return SLAP_CB_CONTINUE;
}

416
static int
417
rwm_op_compare( Operation *op, SlapReply *rs )
418
{
419
420
421
422
423
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	int			rc;
424
	struct berval		mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
425

426
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
427
428

	rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
429
	if ( rc != LDAP_SUCCESS ) {
430
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
431
		send_ldap_error( op, rs, rc, "compareDN massage error" );
432
433
434
435
436
437
438
439
440
		return -1;
	}

	/* if the attribute is an objectClass, try to remap its value */
	if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
			|| op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
	{
		rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
				&mapped_vals[0], RWM_MAP );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
441
		if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
442
443
444
445
446
447
		{
			op->o_bd->bd_info = (BackendInfo *)on->on_info;
			send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
			return -1;

		} else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
448
449
			ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
				op->o_tmpmemctx );
450
451
452
		}

	} else {
453
454
455
456
457
458
459
460
461
462
463
464
465
		struct ldapmapping	*mapping = NULL;
		AttributeDescription	*ad = op->orc_ava->aa_desc;

		( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
				&mapping, RWM_MAP );
		if ( mapping == NULL ) {
			if ( rwmap->rwm_at.drop_missing ) {
				op->o_bd->bd_info = (BackendInfo *)on->on_info;
				send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
				return -1;
			}

		} else {
466
			assert( mapping->m_dst_ad != NULL );
467
			ad = mapping->m_dst_ad;
468
		}
469

470
471
		if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
				|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
472
		{
473
474
475
476
477
			struct berval	*mapped_valsp[2];
			
			mapped_valsp[0] = &mapped_vals[0];
			mapped_valsp[1] = &mapped_vals[1];

478
			mapped_vals[0] = op->orc_ava->aa_value;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
479

480
			rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
481

482
483
484
485
486
487
			if ( rc != LDAP_SUCCESS ) {
				op->o_bd->bd_info = (BackendInfo *)on->on_info;
				send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
				return -1;
			}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
488
			if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
489
490
491
492
				/* NOTE: if we get here, rwm_dnattr_rewrite()
				 * already freed the old value, so now 
				 * it's invalid */
				ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
493
					op->o_tmpmemctx );
494
				ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
495
			}
496
		}
497
		op->orc_ava->aa_desc = ad;
498
499
	}

500
501
	op->o_callback = &roc->cb;

502
503
504
505
	return SLAP_CB_CONTINUE;
}

static int
506
rwm_op_delete( Operation *op, SlapReply *rs )
507
{
508
509
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	int			rc;
510

511
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
512
513

	rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
514
	if ( rc != LDAP_SUCCESS ) {
515
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
516
		send_ldap_error( op, rs, rc, "deleteDN massage error" );
517
		return -1;
518
519
	}

520
521
	op->o_callback = &roc->cb;

522
523
524
525
	return SLAP_CB_CONTINUE;
}

static int
526
rwm_op_modify( Operation *op, SlapReply *rs )
527
{
528
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
529
530
531
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

532
	int			isupdate;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
533
	Modifications		**mlp;
534
	int			rc;
535

536
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
537
538

	rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
539
	if ( rc != LDAP_SUCCESS ) {
540
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
541
		send_ldap_error( op, rs, rc, "modifyDN massage error" );
542
		return -1;
543
544
	}

545
	isupdate = be_shadow_update( op );
546
	for ( mlp = &op->orm_modlist; *mlp; ) {
547
		int			is_oc = 0;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
548
		Modifications		*ml = *mlp;
549
		struct ldapmapping	*mapping = NULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
550

Pierangelo Masarati's avatar
Pierangelo Masarati committed
551
		/* ml points to a temporary mod until needs duplication */
552
553
		if ( ml->sml_desc == slap_schema.si_ad_objectClass 
				|| ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
554
		{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
555
556
			is_oc = 1;

557
		} else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
558
		{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
559
560
561
562
563
564
565
566
567
			ml = ch_malloc( sizeof( Modifications ) );
			*ml = **mlp;
			if ( (*mlp)->sml_values ) {
				ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
				if ( (*mlp)->sml_nvalues ) {
					ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
				}
			}
			*mlp = ml;
568
569
			goto next_mod;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
570
571
572
		} else {
			int			drop_missing;

573
			drop_missing = rwm_mapping( &rwmap->rwm_at,
574
					&ml->sml_desc->ad_cname,
575
576
					&mapping, RWM_MAP );
			if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
Pierangelo Masarati's avatar
Pierangelo Masarati committed
577
			{
578
				goto cleanup_mod;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
579
580
581
			}
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
582
583
584
585
586
		/* duplicate the modlist */
		ml = ch_malloc( sizeof( Modifications ));
		*ml = **mlp;
		*mlp = ml;

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
		if ( ml->sml_values != NULL ) {
			int i, num;
			struct berval *bva;

			for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
				/* count values */ ;

			bva = ch_malloc( (num+1) * sizeof( struct berval ));
			for (i=0; i<num; i++)
				ber_dupbv( &bva[i], &ml->sml_values[i] );
			BER_BVZERO( &bva[i] );
			ml->sml_values = bva;

			if ( ml->sml_nvalues ) {
				bva = ch_malloc( (num+1) * sizeof( struct berval ));
				for (i=0; i<num; i++)
					ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
				BER_BVZERO( &bva[i] );
				ml->sml_nvalues = bva;
			}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
608
609
610
			if ( is_oc ) {
				int	last, j;

611
				last = num-1;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
612

613
				for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
614
615
					struct ldapmapping	*oc_mapping = NULL;
		
616
					( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
617
618
							&oc_mapping, RWM_MAP );
					if ( oc_mapping == NULL ) {
619
620
621
622
623
624
						if ( rwmap->rwm_at.drop_missing ) {
							/* FIXME: we allow to remove objectClasses as well;
							 * if the resulting entry is inconsistent, that's
							 * the relayed database's business...
							 */
							if ( last > j ) {
625
626
								ch_free( ml->sml_values[ j ].bv_val );
								ml->sml_values[ j ] = ml->sml_values[ last ];
627
							}
628
							BER_BVZERO( &ml->sml_values[ last ] );
629
630
							last--;
							j--;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
631
						}
632
	
Pierangelo Masarati's avatar
Pierangelo Masarati committed
633
					} else {
634
635
						ch_free( ml->sml_values[ j ].bv_val );
						ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
636
637
638
639
					}
				}

			} else {
640
				if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
641
						|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
Pierangelo Masarati's avatar
Pierangelo Masarati committed
642
				{
643
					rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
644
645
							ml->sml_values,
							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
646

647
				} else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
648
649
					rc = rwm_referral_rewrite( op, rs,
							"referralAttrDN",
650
651
							ml->sml_values,
							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
652
653
654
					if ( rc != LDAP_SUCCESS ) {
						goto cleanup_mod;
					}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
655
656
657
				}

				if ( rc != LDAP_SUCCESS ) {
658
					goto cleanup_mod;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
659
660
661
662
				}
			}
		}

663
next_mod:;
664
665
		if ( mapping != NULL ) {
			/* use new attribute description */
666
			assert( mapping->m_dst_ad != NULL );
667
			ml->sml_desc = mapping->m_dst_ad;
668
669
		}

670
		mlp = &ml->sml_next;
671
672
673
674
675
676
677
		continue;

cleanup_mod:;
		ml = *mlp;
		*mlp = (*mlp)->sml_next;
		slap_mod_free( &ml->sml_mod, 0 );
		free( ml );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
678
679
	}

680
681
	op->o_callback = &roc->cb;

682
683
684
685
	return SLAP_CB_CONTINUE;
}

static int
686
rwm_op_modrdn( Operation *op, SlapReply *rs )
687
{
688
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
689
690
691
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;
	
692
	int			rc;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
693
	dncookie		dc;
694

695
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
696

697
698
699
700
701
702
703
704
705
706
707
	if ( op->orr_newSup ) {
		struct berval	nnewSup = BER_BVNULL;
		struct berval	newSup = BER_BVNULL;

		/*
		 * Rewrite the new superior, if defined and required
	 	 */
		dc.rwmap = rwmap;
		dc.conn = op->o_conn;
		dc.rs = rs;
		dc.ctx = "newSuperiorDN";
708
709
710
		newSup = *op->orr_newSup;
		nnewSup = *op->orr_nnewSup;
		rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
711
712
713
714
715
716
717
		if ( rc != LDAP_SUCCESS ) {
			op->o_bd->bd_info = (BackendInfo *)on->on_info;
			send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
			return -1;
		}

		if ( op->orr_newSup->bv_val != newSup.bv_val ) {
718
719
720
721
			op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
				op->o_tmpmemctx );
			op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
				op->o_tmpmemctx );
722
723
724
725
726
			*op->orr_newSup = newSup;
			*op->orr_nnewSup = nnewSup;
		}
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
	/*
	 * Rewrite the newRDN, if needed
 	 */
	{
		struct berval	newrdn = BER_BVNULL;
		struct berval	nnewrdn = BER_BVNULL;

		dc.rwmap = rwmap;
		dc.conn = op->o_conn;
		dc.rs = rs;
		dc.ctx = "newRDN";
		newrdn = op->orr_newrdn;
		nnewrdn = op->orr_nnewrdn;
		rc = rwm_dn_massage_pretty_normalize( &dc, &op->orr_newrdn, &newrdn, &nnewrdn );
		if ( rc != LDAP_SUCCESS ) {
			op->o_bd->bd_info = (BackendInfo *)on->on_info;
			send_ldap_error( op, rs, rc, "newRDN massage error" );
			goto err;
		}

		if ( op->orr_newrdn.bv_val != newrdn.bv_val ) {
			op->orr_newrdn = newrdn;
			op->orr_nnewrdn = nnewrdn;
		}
	}

753
754
755
	/*
	 * Rewrite the dn, if needed
 	 */
756
	rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
757
	if ( rc != LDAP_SUCCESS ) {
758
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
759
		send_ldap_error( op, rs, rc, "renameDN massage error" );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
760
761
762
763
764
765
766
767
768
		goto err;
	}

	op->o_callback = &roc->cb;

	rc = SLAP_CB_CONTINUE;

	if ( 0 ) {
err:;
769
770
771
772
773
774
775
776
		if ( op->orr_newSup != roc->ros.orr_newSup ) {
			ch_free( op->orr_newSup->bv_val );
			ch_free( op->orr_nnewSup->bv_val );
			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
			op->orr_newSup = roc->ros.orr_newSup;
			op->orr_nnewSup = roc->ros.orr_nnewSup;
		}
777

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
778
779
780
781
782
783
784
		if ( op->orr_newrdn.bv_val != roc->ros.orr_newrdn.bv_val ) {
			ch_free( op->orr_newrdn.bv_val );
			ch_free( op->orr_nnewrdn.bv_val );
			op->orr_newrdn = roc->ros.orr_newrdn;
			op->orr_nnewrdn = roc->ros.orr_nnewrdn;
		}
	}
785

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
786
	return rc;
787
788
789
}


Pierangelo Masarati's avatar
Pierangelo Masarati committed
790
791
792
793
static int
rwm_swap_attrs( Operation *op, SlapReply *rs )
{
	slap_callback	*cb = op->o_callback;
794
	rwm_op_state *ros = cb->sc_private;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
795

796
	rs->sr_attrs = ros->ors_attrs;
797
798
799
800
801

	/* other overlays might have touched op->ors_attrs, 
	 * so we restore the original version here, otherwise
	 * attribute-mapping might fail */
	op->ors_attrs = ros->mapped_attrs; 
Pierangelo Masarati's avatar
Pierangelo Masarati committed
802
	
803
 	return SLAP_CB_CONTINUE;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
804
805
}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
/*
 * NOTE: this implementation of get/release entry is probably far from
 * optimal.  The rationale consists in intercepting the request directed
 * to the underlying database, in order to rewrite/remap the request,
 * perform it using the modified data, duplicate the resulting entry
 * and finally free it when release is called.
 * This implies that subsequent overlays are not called, as the request
 * is directly shunted to the underlying database.
 */
static int
rwm_entry_release_rw( Operation *op, Entry *e, int rw )
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;

	/* can't be ours */
	if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
		return SLAP_CB_CONTINUE;
	}

	/* just free entry if (probably) ours */
	if ( e->e_private == NULL ) {
		entry_free( e );
		return LDAP_SUCCESS;
	}

	return SLAP_CB_CONTINUE;
}

static int
rwm_entry_get_rw( Operation *op, struct berval *ndn,
	ObjectClass *oc, AttributeDescription *at, int rw, Entry **ep )
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	int			rc;
	dncookie		dc;

	BackendDB		db;
	Operation		op2;
	SlapReply		rs = { REP_SEARCH };

	rwm_op_state		ros = { 0 };

	if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
		return SLAP_CB_CONTINUE;
	}

	/* massage DN */
	op2.o_tag = LDAP_REQ_SEARCH;
	op2 = *op;
	op2.o_req_dn = *ndn;
	op2.o_req_ndn = *ndn;
	rc = rwm_op_dn_massage( &op2, &rs, "searchDN", &ros );
	if ( rc != LDAP_SUCCESS ) {
		return LDAP_OTHER;
	}

	/* map attribute & objectClass */
	if ( at != NULL ) {
	}

	if ( oc != NULL ) {
	}

	/* fetch entry */
	db = *op->o_bd;
	op2.o_bd = &db;
	op2.o_bd->bd_info = (BackendInfo *)on->on_info->oi_orig;
	op2.ors_attrs = slap_anlist_all_attributes;
	rc = op2.o_bd->bd_info->bi_entry_get_rw( &op2, &ros.r_ndn, oc, at, rw, ep );
	if ( rc == LDAP_SUCCESS && *ep != NULL ) {
		rs.sr_entry = *ep;

		/* duplicate & release */
		op2.o_bd->bd_info = (BackendInfo *)on;
		rc = rwm_send_entry( &op2, &rs );
		if ( rc == SLAP_CB_CONTINUE ) {
			*ep = rs.sr_entry;
			rc = LDAP_SUCCESS;
		}
	}

	if ( ros.r_ndn.bv_val != ndn->bv_val ) {
		op->o_tmpfree( ros.r_ndn.bv_val, op->o_tmpmemctx );
	}

	return rc;
}

897
static int
898
rwm_op_search( Operation *op, SlapReply *rs )
899
{
900
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
901
902
903
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

904
	int			rc;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
905
906
907
908
909
910
911
912
	dncookie		dc;

	struct berval		fstr = BER_BVNULL;
	Filter			*f = NULL;

	AttributeName		*an = NULL;

	char			*text = NULL;
913

914
	rwm_op_cb		*roc = rwm_callback_get( op, rs );
915

916
917
918
	rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
		"searchFilter", op->ors_filterstr.bv_val );
	if ( rc == LDAP_SUCCESS )
919
		rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
920
	if ( rc != LDAP_SUCCESS ) {
921
		text = "searchDN massage error";
Pierangelo Masarati's avatar
Pierangelo Masarati committed
922
923
924
925
		goto error_return;
	}

	/*
926
	 * Rewrite the dn if needed
Pierangelo Masarati's avatar
Pierangelo Masarati committed
927
928
929
930
931
932
	 */
	dc.rwmap = rwmap;
	dc.conn = op->o_conn;
	dc.rs = rs;
	dc.ctx = "searchFilterAttrDN";

933
	rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
	if ( rc != LDAP_SUCCESS ) {
		text = "searchFilter/searchFilterAttrDN massage error";
		goto error_return;
	}

	f = str2filter_x( op, fstr.bv_val );

	if ( f == NULL ) {
		text = "massaged filter parse error";
		goto error_return;
	}

	op->ors_filter = f;
	op->ors_filterstr = fstr;

	rc = rwm_map_attrnames( &rwmap->rwm_at, &rwmap->rwm_oc,
			op->ors_attrs, &an, RWM_MAP );
	if ( rc != LDAP_SUCCESS ) {
		text = "attribute list mapping error";
		goto error_return;
954
955
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
956
	op->ors_attrs = an;
957
958
959
	/* store the mapped Attributes for later usage, in
	 * the case that other overlays change op->ors_attrs */
	roc->ros.mapped_attrs = an;
960
961
962
	roc->cb.sc_response = rwm_swap_attrs;

	op->o_callback = &roc->cb;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
963

964
	return SLAP_CB_CONTINUE;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
965
966
967
968
969
970
971

error_return:;
	if ( an != NULL ) {
		ch_free( an );
	}

	if ( f != NULL ) {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
972
		filter_free_x( op, f, 1 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
973
974
975
976
977
978
	}

	if ( !BER_BVISNULL( &fstr ) ) {
		ch_free( fstr.bv_val );
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
979
	rwm_op_rollback( op, rs, &roc->ros );
980
	op->oq_search = roc->ros.oq_search;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
981
	op->o_tmpfree( roc, op->o_tmpmemctx );
982

Pierangelo Masarati's avatar
Pierangelo Masarati committed
983
984
985
	op->o_bd->bd_info = (BackendInfo *)on->on_info;
	send_ldap_error( op, rs, rc, text );

986
	return -1;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
987

988
989
}

990
991
992
993
994
static int
rwm_exop_passwd( Operation *op, SlapReply *rs )
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	int			rc;
995
	rwm_op_cb *roc;
996
997
998
999

	struct berval	id = BER_BVNULL,
			pwold = BER_BVNULL,
			pwnew = BER_BVNULL;
Howard Chu's avatar
Howard Chu committed
1000
	BerElement *ber = NULL;
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017

	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
		return LDAP_SUCCESS;
	}

	if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
		rs->sr_err = LDAP_OTHER;
		return rs->sr_err;
	}

	rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
		&pwold, &pwnew, &rs->sr_text );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		return rs->sr_err;
	}

	if ( !BER_BVISNULL( &id ) ) {
1018
1019
		char idNul = id.bv_val[id.bv_len];
		id.bv_val[id.bv_len] = '\0';
1020
1021
		rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
				&op->o_req_ndn, op->o_tmpmemctx );
1022
		id.bv_val[id.bv_len] = idNul;
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
		if ( rs->sr_err != LDAP_SUCCESS ) {
			rs->sr_text = "Invalid DN";
			return rs->sr_err;
		}

	} else {
		ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
		ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
	}

1033
1034
1035
	roc = rwm_callback_get( op, rs );

	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1036
1037
1038
1039
1040
1041
	if ( rc != LDAP_SUCCESS ) {
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
		send_ldap_error( op, rs, rc, "extendedDN massage error" );
		return -1;
	}

Howard Chu's avatar
Howard Chu committed
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
	ber = ber_alloc_t( LBER_USE_DER );
	if ( !ber ) {
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "No memory";
		return rs->sr_err;
	}
	ber_printf( ber, "{" );
	if ( !BER_BVISNULL( &id )) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, 
			&op->o_req_dn );
	}
	if ( !BER_BVISNULL( &pwold )) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
	}
	if ( !BER_BVISNULL( &pwnew )) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
	}
	ber_printf( ber, "N}" );
	ber_flatten( ber, &op->ore_reqdata );
	ber_free( ber, 1 );
1062

1063
1064
	op->o_callback = &roc->cb;

1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
	return SLAP_CB_CONTINUE;
}

static struct exop {
	struct berval	oid;
	BI_op_extended	*extended;
} exop_table[] = {
	{ BER_BVC(LDAP_EXOP_MODIFY_PASSWD),	rwm_exop_passwd },
	{ BER_BVNULL, NULL }
};

1076
1077
1078
static int
rwm_extended( Operation *op, SlapReply *rs )
{
1079
1080
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	int			rc;
1081
	rwm_op_cb *roc;
1082

1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
	int	i;

	for ( i = 0; exop_table[i].extended != NULL; i++ ) {
		if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
		{
			rc = exop_table[i].extended( op, rs );
			switch ( rc ) {
			case LDAP_SUCCESS:
				break;

			case SLAP_CB_CONTINUE:
			case SLAPD_ABANDON:
				return rc;

			default:
				send_ldap_result( op, rs );
				return rc;
			}
			break;
		}
	}

1105
1106
1107
	roc = rwm_callback_get( op, rs );

	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1108
	if ( rc != LDAP_SUCCESS ) {
1109
		op->o_bd->bd_info = (BackendInfo *)on->on_info;
1110
		send_ldap_error( op, rs, rc, "extendedDN massage error" );
1111
		return -1;
1112
1113
	}

1114
	/* TODO: rewrite/map extended data ? ... */
1115
1116
	op->o_callback = &roc->cb;

1117
	return SLAP_CB_CONTINUE;
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
}

static int
rwm_matched( Operation *op, SlapReply *rs )
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

	struct berval		dn, mdn;
	dncookie		dc;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1129
	int			rc;
1130
1131
1132
1133
1134
1135
1136
1137

	if ( rs->sr_matched == NULL ) {
		return SLAP_CB_CONTINUE;
	}

	dc.rwmap = rwmap;
	dc.conn = op->o_conn;
	dc.rs = rs;
1138
	dc.ctx = "matchedDN";
1139
	ber_str2bv( rs->sr_matched, 0, 0, &dn );
1140
1141
	mdn = dn;
	rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1142
1143
1144
1145
1146
	if ( rc != LDAP_SUCCESS ) {
		rs->sr_err = rc;
		rs->sr_text = "Rewrite error";
		return 1;
	}
1147
1148
1149

	if ( mdn.bv_val != dn.bv_val ) {
		if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1150
			ch_free( (void *)rs->sr_matched );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1151

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
		} else {
			rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
		}
		rs->sr_matched = mdn.bv_val;
	}
	
	return SLAP_CB_CONTINUE;
}

static int
1162
rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
1163
1164
1165
1166
1167
{
	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
	struct ldaprwmap	*rwmap = 
			(struct ldaprwmap *)on->on_bi.bi_private;

1168
1169
1170
	dncookie		dc;
	int			rc;
	Attribute		**ap;
1171
	int			isupdate;
1172
	int			check_duplicate_attrs = 0;
1173
1174

	/*