modrdn.c 16.5 KB
Newer Older
1
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
5
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
 */

18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * LDAP v3 newSuperior support.
 *
 * Copyright 1999, Juan C. Gomez, All rights reserved.
 * This software is not subject to any license of Silicon Graphics 
 * Inc. or Purdue University.
 *
 * Redistribution and use in source and binary forms are permitted
 * without restriction or fee of any kind as long as this notice
 * is preserved.
 *
 */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
31
32
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
33
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
34
35
36
37

#include <ac/socket.h>
#include <ac/string.h>

38
#include "ldap_pvt.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
39
#include "slap.h"
40
#ifdef LDAP_SLAPI
41
#include "slapi.h"
42
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
43

44
int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
45
do_modrdn(
46
47
    Operation	*op,
    SlapReply	*rs
Kurt Zeilenga's avatar
Kurt Zeilenga committed
48
49
)
{
50
51
52
	struct berval dn = { 0, NULL };
	struct berval newrdn = { 0, NULL };
	struct berval newSuperior = { 0, NULL };
53
	ber_int_t	deloldrdn;
54

55
	struct berval pnewSuperior = { 0, NULL };
56

57
	struct berval nnewSuperior = { 0, NULL };
58

59
	Backend	*newSuperior_be = NULL;
60
	ber_len_t	length;
61
	int manageDSAit;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
62

63
#ifdef LDAP_SLAPI
64
	Slapi_PBlock *pb = op->o_pb;
65
#endif
66

67
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
68
	LDAP_LOG( OPERATION, ENTRY, "do_modrdn: begin\n", 0, 0, 0 );
69
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
70
	Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
71
72
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
73
74
75
76
77
78
79

	/*
	 * Parse the modrdn request.  It looks like this:
	 *
	 *	ModifyRDNRequest := SEQUENCE {
	 *		entry	DistinguishedName,
	 *		newrdn	RelativeDistinguishedName
80
81
	 *		deleteoldrdn	BOOLEAN,
	 *		newSuperior	[0] LDAPDN OPTIONAL (v3 Only!)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
82
83
84
	 *	}
	 */

85
	if ( ber_scanf( op->o_ber, "{mmb", &dn, &newrdn, &deloldrdn )
86
87
	    == LBER_ERROR )
	{
88
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
89
		LDAP_LOG( OPERATION, ERR, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
90
#else
Kurt Zeilenga's avatar
Kurt Zeilenga committed
91
		Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
92
93
#endif

94
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
95
		return SLAPD_DISCONNECT;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
97
	}

98
99
100
	/* Check for newSuperior parameter, if present scan it */

	if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
101
		if ( op->o_protocol < LDAP_VERSION3 ) {
102
103
104
			/* Conection record indicates v2 but field 
			 * newSuperior is present: report error.
			 */
105
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
106
107
			LDAP_LOG( OPERATION, ERR,
				"do_modrdn: (v2) invalid field newSuperior.\n", 0, 0, 0 );
108
#else
109
			Debug( LDAP_DEBUG_ANY,
110
111
			    "modrdn(v2): invalid field newSuperior!\n",
			    0, 0, 0 );
112
113
#endif

114
			send_ldap_discon( op, rs,
115
				LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
116
			rs->sr_err = SLAPD_DISCONNECT;
Howard Chu's avatar
Howard Chu committed
117
			goto cleanup;
118
		}
119

120
		if ( ber_scanf( op->o_ber, "m", &newSuperior ) 
121
122
		     == LBER_ERROR ) {

123
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
124
125
			LDAP_LOG( OPERATION, ERR,
				"do_modrdn: ber_scanf(\"m\") failed\n", 0, 0, 0 );
126
#else
127
			Debug( LDAP_DEBUG_ANY, "ber_scanf(\"m\") failed\n",
128
				0, 0, 0 );
129
130
#endif

131
			send_ldap_discon( op, rs,
132
				LDAP_PROTOCOL_ERROR, "decoding error" );
133
			rs->sr_err = SLAPD_DISCONNECT;
Howard Chu's avatar
Howard Chu committed
134
			goto cleanup;
135
		}
Howard Chu's avatar
Howard Chu committed
136
137
		op->orr_newSup = &pnewSuperior;
		op->orr_nnewSup = &nnewSuperior;
138
	}
139

140
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
141
	LDAP_LOG( OPERATION, ARGS, 
142
143
		"do_modrdn: dn (%s) newrdn (%s) newsuperior(%s)\n",
		dn.bv_val, newrdn.bv_val,
Julius Enarusai's avatar
   
Julius Enarusai committed
144
		newSuperior.bv_len ? newSuperior.bv_val : "" );
145
#else
146
147
	Debug( LDAP_DEBUG_ARGS,
	    "do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n",
148
149
		dn.bv_val, newrdn.bv_val,
		newSuperior.bv_len ? newSuperior.bv_val : "" );
150
151
#endif

152
	if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
153
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
154
		LDAP_LOG( OPERATION, ERR, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
155
#else
156
		Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
157
158
#endif

159
		send_ldap_discon( op, rs,
160
			LDAP_PROTOCOL_ERROR, "decoding error" );
161
		rs->sr_err = SLAPD_DISCONNECT;
Howard Chu's avatar
Howard Chu committed
162
		goto cleanup;
163
164
	}

165
	if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
166
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
167
		LDAP_LOG( OPERATION, ERR, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
168
#else
169
		Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
170
171
#endif

Gary Williams's avatar
Gary Williams committed
172
		/* get_ctrls has sent results.	Now clean up. */
Howard Chu's avatar
Howard Chu committed
173
		goto cleanup;
174
175
	} 

Howard Chu's avatar
Howard Chu committed
176
	rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
177
	if( rs->sr_err != LDAP_SUCCESS ) {
178
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
179
		LDAP_LOG( OPERATION, INFO, 
180
			"do_modrdn: conn %d  invalid dn (%s)\n",
181
			op->o_connid, dn.bv_val, 0 );
182
#else
183
184
		Debug( LDAP_DEBUG_ANY,
			"do_modrdn: invalid dn (%s)\n", dn.bv_val, 0, 0 );
185
#endif
186
		send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
187
188
189
		goto cleanup;
	}

190
	if( op->o_req_ndn.bv_len == 0 ) {
191
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
192
193
		LDAP_LOG( OPERATION, ERR,
			"do_modrdn:  attempt to modify root DSE.\n", 0, 0, 0 );
194
#else
195
		Debug( LDAP_DEBUG_ANY, "do_modrdn: root dse!\n", 0, 0, 0 );
196
197
#endif

198
199
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"cannot rename the root DSE" );
200
		goto cleanup;
201

202
	} else if ( bvmatch( &op->o_req_ndn, &global_schemandn ) ) {
203
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
204
		LDAP_LOG( OPERATION, ERR,
205
206
			"do_modrdn: attempt to modify subschema subentry: %s (%ld)\n",
			global_schemandn.bv_val, (long) global_schemandn.bv_len, 0 );
207
#else
208
209
		Debug( LDAP_DEBUG_ANY, "do_modrdn: subschema subentry: %s (%ld)\n",
			global_schemandn.bv_val, (long) global_schemandn.bv_len, 0 );
210
211
#endif

212
213
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"cannot rename subschema subentry" );
214
		goto cleanup;
215
216
	}

217
218
	/* FIXME: should have/use rdnPretty / rdnNormalize routines */

Howard Chu's avatar
Howard Chu committed
219
	rs->sr_err = dnPrettyNormal( NULL, &newrdn, &op->orr_newrdn, &op->orr_nnewrdn, op->o_tmpmemctx );
220
	if( rs->sr_err != LDAP_SUCCESS ) {
221
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
222
		LDAP_LOG( OPERATION, INFO, 
223
			"do_modrdn: conn %d  invalid newrdn (%s)\n",
224
			op->o_connid, newrdn.bv_val, 0 );
225
226
227
228
#else
		Debug( LDAP_DEBUG_ANY,
			"do_modrdn: invalid newrdn (%s)\n", newrdn.bv_val, 0, 0 );
#endif
229
		send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" );
230
231
232
		goto cleanup;
	}

Howard Chu's avatar
Howard Chu committed
233
	if( rdnValidate( &op->orr_newrdn ) != LDAP_SUCCESS ) {
234
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
235
		LDAP_LOG( OPERATION, ERR, 
Howard Chu's avatar
Howard Chu committed
236
			"do_modrdn: invalid rdn (%s).\n", op->orr_newrdn.bv_val, 0, 0 );
237
238
#else
		Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid rdn (%s)\n",
Howard Chu's avatar
Howard Chu committed
239
			op->orr_newrdn.bv_val, 0, 0 );
240
241
#endif

242
		send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" );
243
244
245
		goto cleanup;
	}

Howard Chu's avatar
Howard Chu committed
246
	if( op->orr_newSup ) {
247
		rs->sr_err = dnPrettyNormal( NULL, &newSuperior, &pnewSuperior,
Howard Chu's avatar
Howard Chu committed
248
			&nnewSuperior, op->o_tmpmemctx );
249
		if( rs->sr_err != LDAP_SUCCESS ) {
250
#ifdef NEW_LOGGING
Julius Enarusai's avatar
   
Julius Enarusai committed
251
			LDAP_LOG( OPERATION, INFO, 
252
				"do_modrdn: conn %d  invalid newSuperior (%s)\n",
253
				op->o_connid, newSuperior.bv_val, 0 );
254
255
256
257
258
#else
			Debug( LDAP_DEBUG_ANY,
				"do_modrdn: invalid newSuperior (%s)\n",
				newSuperior.bv_val, 0, 0 );
#endif
259
			send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid newSuperior" );
260
261
262
263
			goto cleanup;
		}
	}

264
	Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu MODRDN dn=\"%s\"\n",
265
	    op->o_connid, op->o_opid, op->o_req_dn.bv_val, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
266

267
268
	manageDSAit = get_manageDSAit( op );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
269
270
271
272
273
	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
274
275
276
277
	if ( (op->o_bd = select_backend( &op->o_req_ndn, manageDSAit, 0 )) == NULL ) {
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
		if (!rs->sr_ref) rs->sr_ref = default_referral;
278

Pierangelo Masarati's avatar
Pierangelo Masarati committed
279
280
281
282
283
284
285
286
287
		if ( rs->sr_ref != NULL ) {
			rs->sr_err = LDAP_REFERRAL;
			send_ldap_result( op, rs );

			if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
		} else {
			send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
					"referral missing" );
		}
Howard Chu's avatar
Howard Chu committed
288
		goto cleanup;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
289
290
	}

291
	/* check restrictions */
292
293
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
294
		goto cleanup;
295
296
	}

297
	/* check for referrals */
298
	if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
299
300
301
		goto cleanup;
	}

302
303
304
	/* Make sure that the entry being changed and the newSuperior are in 
	 * the same backend, otherwise we return an error.
	 */
Howard Chu's avatar
Howard Chu committed
305
	if( op->orr_newSup ) {
Howard Chu's avatar
Howard Chu committed
306
		newSuperior_be = select_backend( &nnewSuperior, 0, 0 );
307

308
309
310
311
		if ( newSuperior_be != op->o_bd ) {
			/* newSuperior is in different backend */
			send_ldap_error( op, rs, LDAP_AFFECTS_MULTIPLE_DSAS,
				"cannot rename between DSAs" );
312

Howard Chu's avatar
Howard Chu committed
313
			goto cleanup;
314
		}
315
	}
316

317
#if defined( LDAP_SLAPI )
Luke Howard's avatar
Luke Howard committed
318
	slapi_x_pblock_set_operation( pb, op );
319
	slapi_pblock_set( pb, SLAPI_MODRDN_TARGET, (void *)dn.bv_val );
320
321
322
323
	slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN, (void *)newrdn.bv_val );
	slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR,
			(void *)newSuperior.bv_val );
	slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN, (void *)deloldrdn );
324
	slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)manageDSAit );
325

326
	rs->sr_err = doPluginFNs( op->o_bd, SLAPI_PLUGIN_PRE_MODRDN_FN, pb );
Howard Chu's avatar
Howard Chu committed
327
	if ( rs->sr_err < 0 ) {
328
		/*
329
330
		 * A preoperation plugin failure will abort the
		 * entire operation.
331
332
		 */
#ifdef NEW_LOGGING
333
		LDAP_LOG( OPERATION, INFO, "do_modrdn: modrdn preoperation plugin "
334
				"failed\n", 0, 0, 0 );
335
#else
336
		Debug(LDAP_DEBUG_TRACE, "do_modrdn: modrdn preoperation plugin "
337
				"failed.\n", 0, 0, 0);
338
#endif
339
340
		if ( ( slapi_pblock_get( pb, SLAPI_RESULT_CODE, (void *)&rs->sr_err ) != 0 ) ||
		     rs->sr_err == LDAP_SUCCESS ) {
341
			rs->sr_err = LDAP_OTHER;
342
		}
343
		goto cleanup;
344
345
346
	}
#endif /* defined( LDAP_SLAPI ) */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
347
	/*
348
349
	 * do the modrdn if 1 && (2 || 3)
	 * 1) there is a modrdn function implemented in this backend;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
350
	 * 2) this backend is master for what it holds;
351
	 * 3) it's a replica and the dn supplied is the update_ndn.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
352
	 */
353
	if ( op->o_bd->be_modrdn ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
354
		/* do the update here */
355
		int repl_user = be_isupdate( op->o_bd, &op->o_ndn );
356
#ifndef SLAPD_MULTIMASTER
357
358
		if ( !op->o_bd->syncinfo &&
					( !op->o_bd->be_update_ndn.bv_len || repl_user ))
359
360
#else
		if ( !op->o_bd->syncinfo )
361
#endif
362
		{
Howard Chu's avatar
Howard Chu committed
363
			op->orr_deleteoldrdn = deloldrdn;
364
			if ( (op->o_bd->be_modrdn)( op, rs ) == 0
365
#ifdef SLAPD_MULTIMASTER
366
				&& ( !op->o_bd->be_update_ndn.bv_len || !repl_user )
367
368
#endif
			) {
369
				replog( op );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
370
			}
371
#ifndef SLAPD_MULTIMASTER
Kurt Zeilenga's avatar
Kurt Zeilenga committed
372
		} else {
373
374
			BerVarray defref = NULL;
			if ( op->o_bd->syncinfo ) {
375
				defref = op->o_bd->syncinfo->provideruri_bv;
376
			} else {
377
378
379
				defref = op->o_bd->be_update_refs
						? op->o_bd->be_update_refs : default_referral;
			}
380
381
382
383
384
385
386
387
388
389
390
391
392
393
			if ( defref != NULL ) {
				rs->sr_ref = referral_rewrite( defref,
					NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
				if (!rs->sr_ref) rs->sr_ref = defref;

				rs->sr_err = LDAP_REFERRAL;
				send_ldap_result( op, rs );

				if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref );
			} else {
				send_ldap_error( op, rs,
					LDAP_UNWILLING_TO_PERFORM,
					"referral missing" );
			}
394
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
395
396
		}
	} else {
397
398
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"operation not supported within namingContext" );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
399
400
	}

401
#if defined( LDAP_SLAPI )
Howard Chu's avatar
Howard Chu committed
402
	if ( doPluginFNs( op->o_bd, SLAPI_PLUGIN_POST_MODRDN_FN, pb ) < 0 ) {
403
#ifdef NEW_LOGGING
404
		LDAP_LOG( OPERATION, INFO, "do_modrdn: modrdn postoperation plugins "
405
				"failed\n", 0, 0, 0 );
406
#else
407
		Debug(LDAP_DEBUG_TRACE, "do_modrdn: modrdn postoperation plugins "
408
				"failed.\n", 0, 0, 0);
409
410
411
412
#endif
	}
#endif /* defined( LDAP_SLAPI ) */

Howard Chu's avatar
Howard Chu committed
413
cleanup:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
414
415
416

	slap_graduate_commit_csn( op );

417
418
	op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
	op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
419

420
421
	op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx );	
	op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx );	
422

423
424
	if ( pnewSuperior.bv_val ) op->o_tmpfree( pnewSuperior.bv_val, op->o_tmpmemctx );
	if ( nnewSuperior.bv_val ) op->o_tmpfree( nnewSuperior.bv_val, op->o_tmpmemctx );
425

426
	return rs->sr_err;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
427
}
428
429
430
431

int
slap_modrdn2mods(
	Operation	*op,
432
	SlapReply	*rs,
433
	Entry		*e,
Howard Chu's avatar
Howard Chu committed
434
435
	LDAPRDN		old_rdn,
	LDAPRDN		new_rdn,
436
437
438
	Modifications	**pmod )
{
	Modifications	*mod = NULL;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
439
	Modifications	**modtail = &mod;
440
	int		a_cnt, d_cnt;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
441
	int repl_user;
442

443
	assert( new_rdn != NULL );
Howard Chu's avatar
Howard Chu committed
444
	assert( !op->orr_deleteoldrdn || old_rdn != NULL );
445

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
446
447
	repl_user = be_isupdate( op->o_bd, &op->o_ndn );

448
	/* Add new attribute values to the entry */
Howard Chu's avatar
Howard Chu committed
449
	for ( a_cnt = 0; new_rdn[a_cnt]; a_cnt++ ) {
450
451
452
		AttributeDescription	*desc = NULL;
		Modifications 		*mod_tmp;

Howard Chu's avatar
Howard Chu committed
453
		rs->sr_err = slap_bv2ad( &new_rdn[a_cnt]->la_attr, &desc, &rs->sr_text );
454

455
		if ( rs->sr_err != LDAP_SUCCESS ) {
456
457
458
#ifdef NEW_LOGGING
			LDAP_LOG ( OPERATION, ERR, 
				"slap_modrdn2modlist: %s: %s (new)\n", 
459
				rs->sr_text, 
Howard Chu's avatar
Howard Chu committed
460
				new_rdn[ a_cnt ]->la_attr.bv_val, 0 );
461
462
463
#else
			Debug( LDAP_DEBUG_TRACE,
				"slap_modrdn2modlist: %s: %s (new)\n",
464
				rs->sr_text, 
Howard Chu's avatar
Howard Chu committed
465
				new_rdn[ a_cnt ]->la_attr.bv_val, 0 );
466
467
468
469
470
#endif
			goto done;		
		}

		/* ACL check of newly added attrs */
471
		if ( op->o_bd && !access_allowed( op, e, desc,
Howard Chu's avatar
Howard Chu committed
472
			&new_rdn[a_cnt]->la_value, ACL_WRITE, NULL ) ) {
473
474
475
476
#ifdef NEW_LOGGING
			LDAP_LOG ( OPERATION, ERR, 
				"slap_modrdn2modlist: access to attr \"%s\" "
				"(new) not allowed\n", 
Howard Chu's avatar
Howard Chu committed
477
				new_rdn[a_cnt]->la_attr.bv_val, 0, 0 );
478
479
480
481
#else
			Debug( LDAP_DEBUG_TRACE,
				"slap_modrdn2modlist: access to attr \"%s\" "
				"(new) not allowed\n", 
Howard Chu's avatar
Howard Chu committed
482
				new_rdn[ a_cnt ]->la_attr.bv_val, 0, 0 );
483
#endif
484
			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
485
486
487
488
			goto done;
		}

		/* Apply modification */
489
490
		mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications )
			+ 4 * sizeof( struct berval ) );
491
		mod_tmp->sml_desc = desc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
492
		mod_tmp->sml_values = ( BerVarray )( mod_tmp + 1 );
Howard Chu's avatar
Howard Chu committed
493
		mod_tmp->sml_values[0] = new_rdn[a_cnt]->la_value;
494
495
496
497
		mod_tmp->sml_values[1].bv_val = NULL;
		if( desc->ad_type->sat_equality->smr_normalize) {
			mod_tmp->sml_nvalues = &mod_tmp->sml_values[2];
			(void) (*desc->ad_type->sat_equality->smr_normalize)(
498
				SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
499
500
501
				desc->ad_type->sat_syntax,
				desc->ad_type->sat_equality,
				&mod_tmp->sml_values[0],
Howard Chu's avatar
Howard Chu committed
502
				&mod_tmp->sml_nvalues[0], op->o_tmpmemctx );
503
504
505
506
			mod_tmp->sml_nvalues[1].bv_val = NULL;
		} else {
			mod_tmp->sml_nvalues = NULL;
		}
507
508
509
510
511
512
		mod_tmp->sml_op = SLAP_MOD_SOFTADD;
		mod_tmp->sml_next = mod;
		mod = mod_tmp;
	}

	/* Remove old rdn value if required */
Howard Chu's avatar
Howard Chu committed
513
	if ( op->orr_deleteoldrdn ) {
Howard Chu's avatar
Howard Chu committed
514
		for ( d_cnt = 0; old_rdn[d_cnt]; d_cnt++ ) {
515
516
517
			AttributeDescription	*desc = NULL;
			Modifications 		*mod_tmp;

Howard Chu's avatar
Howard Chu committed
518
			rs->sr_err = slap_bv2ad( &old_rdn[d_cnt]->la_attr, &desc, &rs->sr_text );
519
			if ( rs->sr_err != LDAP_SUCCESS ) {
520
521
522
#ifdef NEW_LOGGING
				LDAP_LOG ( OPERATION, ERR, 
					"slap_modrdn2modlist: %s: %s (old)\n", 
523
					rs->sr_text, 
Howard Chu's avatar
Howard Chu committed
524
					old_rdn[d_cnt]->la_attr.bv_val, 
525
526
527
528
					0 );
#else
				Debug( LDAP_DEBUG_TRACE,
					"slap_modrdn2modlist: %s: %s (old)\n",
529
					rs->sr_text, 
Howard Chu's avatar
Howard Chu committed
530
					old_rdn[d_cnt]->la_attr.bv_val, 
531
532
533
534
535
536
					0 );
#endif
				goto done;		
			}

			/* ACL check of newly added attrs */
537
			if ( op->o_bd && !access_allowed( op, e, desc,
Howard Chu's avatar
Howard Chu committed
538
				&old_rdn[d_cnt]->la_value, ACL_WRITE, 
539
540
541
542
543
				NULL ) ) {
#ifdef NEW_LOGGING
				LDAP_LOG ( OPERATION, ERR, 
					"slap_modrdn2modlist: access "
					"to attr \"%s\" (old) not allowed\n", 
Howard Chu's avatar
Howard Chu committed
544
					old_rdn[ d_cnt ]->la_attr.bv_val, 
545
546
547
548
549
					0, 0 );
#else
				Debug( LDAP_DEBUG_TRACE,
					"slap_modrdn2modlist: access "
					"to attr \"%s\" (old) not allowed\n", 
Howard Chu's avatar
Howard Chu committed
550
					old_rdn[ d_cnt ]->la_attr.bv_val,
551
552
					0, 0 );
#endif
553
				rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
554
555
556
557
				goto done;
			}

			/* Apply modification */
558
			mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications )
559
				+ 4 * sizeof ( struct berval ) );
560
			mod_tmp->sml_desc = desc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
561
			mod_tmp->sml_values = ( BerVarray )(mod_tmp+1);
Howard Chu's avatar
Howard Chu committed
562
			mod_tmp->sml_values[0] = old_rdn[d_cnt]->la_value;
563
564
565
566
			mod_tmp->sml_values[1].bv_val = NULL;
			if( desc->ad_type->sat_equality->smr_normalize) {
				mod_tmp->sml_nvalues = &mod_tmp->sml_values[2];
				(void) (*desc->ad_type->sat_equality->smr_normalize)(
567
					SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
568
569
570
					desc->ad_type->sat_syntax,
					desc->ad_type->sat_equality,
					&mod_tmp->sml_values[0],
Howard Chu's avatar
Howard Chu committed
571
					&mod_tmp->sml_nvalues[0], op->o_tmpmemctx );
572
573
574
575
				mod_tmp->sml_nvalues[1].bv_val = NULL;
			} else {
				mod_tmp->sml_nvalues = NULL;
			}
576
577
578
579
580
581
582
			mod_tmp->sml_op = LDAP_MOD_DELETE;
			mod_tmp->sml_next = mod;
			mod = mod_tmp;
		}
	}
	
done:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

	if ( !repl_user ) {
		char textbuf[ SLAP_TEXT_BUFLEN ];
		size_t textlen = sizeof textbuf;

		for( modtail = &mod;
			*modtail != NULL;
			modtail = &(*modtail)->sml_next )
		{
			/* empty */
		}

		rs->sr_err = slap_mods_opattrs( op, mod, modtail, &rs->sr_text, textbuf, textlen );
	}

598
	/* LDAP v2 supporting correct attribute handling. */
599
	if ( rs->sr_err != LDAP_SUCCESS && mod != NULL ) {
600
601
602
603
604
605
606
607
608
		Modifications *tmp;
		for ( ; mod; mod = tmp ) {
			tmp = mod->sml_next;
			ch_free( mod );
		}
	}

	*pmod = mod;

609
	return rs->sr_err;
610
}