3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * Copyright (c) 1995 Regents of the University of Michigan.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that this notice is preserved and that due credit is given
12 * to the University of Michigan at Ann Arbor. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission. This software
15 * is provided ``as is'' without express or implied warranty.
19 * LDAP v3 newSuperior support.
21 * Copyright 1999, Juan C. Gomez, All rights reserved.
22 * This software is not subject to any license of Silicon Graphics
23 * Inc. or Purdue University.
25 * Redistribution and use in source and binary forms are permitted
26 * without restriction or fee of any kind as long as this notice
35 #include <ac/socket.h>
36 #include <ac/string.h>
47 struct berval dn = { 0, NULL };
48 struct berval newrdn = { 0, NULL };
49 struct berval newSuperior = { 0, NULL };
52 struct berval *pdn = NULL;
53 struct berval *pnewrdn = NULL;
54 struct berval *pnewSuperior = NULL;
56 struct berval *ndn = NULL;
57 struct berval *nnewrdn = NULL;
58 struct berval *nnewSuperior = NULL;
61 Backend *newSuperior_be = NULL;
68 LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
69 "do_modrdn: begin\n" ));
71 Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
76 * Parse the modrdn request. It looks like this:
78 * ModifyRDNRequest := SEQUENCE {
79 * entry DistinguishedName,
80 * newrdn RelativeDistinguishedName
81 * deleteoldrdn BOOLEAN,
82 * newSuperior [0] LDAPDN OPTIONAL (v3 Only!)
86 if ( ber_scanf( op->o_ber, "{oob", &dn, &newrdn, &deloldrdn )
90 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
91 "do_modrdn: ber_scanf failed\n" ));
93 Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
96 send_ldap_disconnect( conn, op,
97 LDAP_PROTOCOL_ERROR, "decoding error" );
98 return SLAPD_DISCONNECT;
101 /* Check for newSuperior parameter, if present scan it */
103 if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
104 if ( op->o_protocol < LDAP_VERSION3 ) {
105 /* Conection record indicates v2 but field
106 * newSuperior is present: report error.
109 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
110 "do_modrdn: (v2) invalid field newSuperior.\n" ));
112 Debug( LDAP_DEBUG_ANY,
113 "modrdn(v2): invalid field newSuperior!\n",
117 send_ldap_disconnect( conn, op,
118 LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
119 rc = SLAPD_DISCONNECT;
123 if ( ber_scanf( op->o_ber, "o", &newSuperior )
127 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
128 "do_modrdn: ber_scanf(\"a\") failed\n" ));
130 Debug( LDAP_DEBUG_ANY, "ber_scanf(\"a\") failed\n",
134 send_ldap_disconnect( conn, op,
135 LDAP_PROTOCOL_ERROR, "decoding error" );
136 rc = SLAPD_DISCONNECT;
142 LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
143 "do_modrdn: dn (%s) newrdn (%s) newsuperior(%s)\n",
144 dn.bv_val, newrdn.bv_val,
145 newSuperior.bv_len ? newSuperior.bv_val : "" ));
147 Debug( LDAP_DEBUG_ARGS,
148 "do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n",
149 dn.bv_val, newrdn.bv_val,
150 newSuperior.bv_len ? newSuperior.bv_val : "" );
153 if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
155 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
156 "do_modrdn: ber_scanf failed\n" ));
158 Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
161 send_ldap_disconnect( conn, op,
162 LDAP_PROTOCOL_ERROR, "decoding error" );
163 rc = SLAPD_DISCONNECT;
167 if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
169 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
170 "do_modrdn: get_ctrls failed\n" ));
172 Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
175 /* get_ctrls has sent results. Now clean up. */
179 rc = dnPretty( NULL, &dn, &pdn );
180 if( rc != LDAP_SUCCESS ) {
182 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
183 "do_modrdn: conn %d invalid dn (%s)\n",
184 conn->c_connid, dn.bv_val ));
186 Debug( LDAP_DEBUG_ANY,
187 "do_modrdn: invalid dn (%s)\n", dn.bv_val, 0, 0 );
189 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
190 "invalid DN", NULL, NULL );
194 rc = dnNormalize( NULL, &dn, &ndn );
195 if( rc != LDAP_SUCCESS ) {
197 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
198 "do_modrdn: conn %d invalid dn (%s)\n",
199 conn->c_connid, pdn->bv_val ));
201 Debug( LDAP_DEBUG_ANY,
202 "do_modrdn: invalid dn (%s)\n", pdn->bv_val, 0, 0 );
204 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
205 "invalid DN", NULL, NULL );
209 if( ndn->bv_len == 0 ) {
211 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
212 "do_modrdn: attempt to modify root DSE.\n" ));
214 Debug( LDAP_DEBUG_ANY, "do_modrdn: root dse!\n", 0, 0, 0 );
217 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
218 NULL, "cannot rename the root DSE", NULL, NULL );
221 #ifdef SLAPD_SCHEMA_DN
222 } else if ( strcasecmp( ndn->bv_val, SLAPD_SCHEMA_DN ) == 0 ) {
224 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
225 "do_modrdn: attempt to modify subschema subentry\n" ));
227 Debug( LDAP_DEBUG_ANY, "do_modrdn: subschema subentry!\n", 0, 0, 0 );
230 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
231 NULL, "cannot rename subschema subentry", NULL, NULL );
236 /* FIXME: should have/use rdnPretty / rdnNormalize routines */
238 rc = dnPretty( NULL, &newrdn, &pnewrdn );
239 if( rc != LDAP_SUCCESS ) {
241 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
242 "do_modrdn: conn %d invalid newrdn (%s)\n",
243 conn->c_connid, newrdn.bv_val ));
245 Debug( LDAP_DEBUG_ANY,
246 "do_modrdn: invalid newrdn (%s)\n", newrdn.bv_val, 0, 0 );
248 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
249 "invalid new RDN", NULL, NULL );
253 rc = dnNormalize( NULL, &newrdn, &nnewrdn );
254 if( rc != LDAP_SUCCESS ) {
256 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
257 "do_modrdn: conn %d invalid newrdn (%s)\n",
258 conn->c_connid, pnewrdn->bv_val ));
260 Debug( LDAP_DEBUG_ANY,
261 "do_modrdn: invalid newrdn (%s)\n", pnewrdn->bv_val, 0, 0 );
263 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
264 "invalid new RDN", NULL, NULL );
268 if( !nnewrdn->bv_len || !rdn_validate( pnewrdn->bv_val ) ) {
270 LDAP_LOG(( "operation", LDAP_LEVEL_ERR,
271 "do_modrdn: invalid rdn (%s).\n", pnewrdn->bv_val ));
273 Debug( LDAP_DEBUG_ANY, "do_modrdn: invalid rdn (%s)\n",
274 pnewrdn->bv_val, 0, 0 );
277 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
278 "invalid new RDN", NULL, NULL );
282 if( newSuperior.bv_len ) {
283 rc = dnPretty( NULL, &newSuperior, &pnewSuperior );
284 if( rc != LDAP_SUCCESS ) {
286 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
287 "do_modrdn: conn %d invalid newSuperior (%s)\n",
288 conn->c_connid, newSuperior.bv_val ));
290 Debug( LDAP_DEBUG_ANY,
291 "do_modrdn: invalid newSuperior (%s)\n",
292 newSuperior.bv_val, 0, 0 );
294 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
295 "invalid newSuperior", NULL, NULL );
299 rc = dnNormalize( NULL, &newSuperior, &nnewSuperior );
300 if( rc != LDAP_SUCCESS ) {
302 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
303 "do_modrdn: conn %d invalid newSuperior (%s)\n",
304 conn->c_connid, pnewSuperior->bv_val ));
306 Debug( LDAP_DEBUG_ANY,
307 "do_modrdn: invalid newSuperior (%s)\n",
308 pnewSuperior->bv_val, 0, 0 );
310 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
311 "invalid newSuperior", NULL, NULL );
316 Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d MODRDN dn=\"%s\"\n",
317 op->o_connid, op->o_opid, pdn->bv_val, 0, 0 );
319 manageDSAit = get_manageDSAit( op );
322 * We could be serving multiple database backends. Select the
323 * appropriate one, or send a referral to our "referral server"
324 * if we don't hold it.
326 if ( (be = select_backend( ndn, manageDSAit, 0 )) == NULL ) {
327 struct berval **ref = referral_rewrite( default_referral,
328 NULL, dn.bv_val, LDAP_SCOPE_DEFAULT );
330 send_ldap_result( conn, op, rc = LDAP_REFERRAL,
331 NULL, NULL, ref ? ref : default_referral, NULL );
337 /* check restrictions */
338 rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
339 if( rc != LDAP_SUCCESS ) {
340 send_ldap_result( conn, op, rc,
341 NULL, text, NULL, NULL );
345 /* check for referrals */
346 rc = backend_check_referrals( be, conn, op, pdn, ndn );
347 if ( rc != LDAP_SUCCESS ) {
351 /* Make sure that the entry being changed and the newSuperior are in
352 * the same backend, otherwise we return an error.
354 if( newSuperior.bv_len ) {
355 newSuperior_be = select_backend( nnewSuperior, 0, 0 );
357 if ( newSuperior_be != be ) {
358 /* newSuperior is in same backend */
359 rc = LDAP_AFFECTS_MULTIPLE_DSAS;
361 send_ldap_result( conn, op, rc,
362 NULL, "cannot rename between DSAa", NULL, NULL );
367 /* deref suffix alias if appropriate */
368 suffix_alias( be, nnewSuperior );
371 /* deref suffix alias if appropriate */
372 suffix_alias( be, ndn );
375 * do the add if 1 && (2 || 3)
376 * 1) there is an add function implemented in this backend;
377 * 2) this backend is master for what it holds;
378 * 3) it's a replica and the dn supplied is the update_ndn.
380 if ( be->be_modrdn ) {
381 /* do the update here */
382 int repl_user = be_isupdate( be, &op->o_ndn );
383 #ifndef SLAPD_MULTIMASTER
384 if ( !be->be_update_ndn.bv_len || repl_user )
387 if ( (*be->be_modrdn)( be, conn, op, pdn->bv_val, ndn->bv_val,
388 pnewrdn->bv_val, deloldrdn,
389 pnewSuperior ? pnewSuperior->bv_val : NULL ) == 0
390 #ifdef SLAPD_MULTIMASTER
391 && ( !be->be_update_ndn.bv_len || !repl_user )
394 struct slap_replog_moddn moddn;
395 moddn.newrdn = pnewrdn;
396 moddn.deloldrdn = deloldrdn;
397 moddn.newsup = pnewSuperior;
399 replog( be, op, pdn, ndn, &moddn );
401 #ifndef SLAPD_MULTIMASTER
403 struct berval **defref = be->be_update_refs
404 ? be->be_update_refs : default_referral;
405 struct berval **ref = referral_rewrite( defref,
406 NULL, pdn->bv_val, LDAP_SCOPE_DEFAULT );
408 send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
409 ref ? ref : defref, NULL );
415 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
416 NULL, "operation not supported within namingContext",
422 if( pdn != NULL ) ber_bvfree( pdn );
423 if( ndn != NULL ) ber_bvfree( ndn );
425 free( newrdn.bv_val );
426 if( pnewrdn != NULL ) ber_bvfree( pnewrdn );
427 if( nnewrdn != NULL ) ber_bvfree( nnewrdn );
429 free( newSuperior.bv_val );
430 if ( pnewSuperior != NULL ) ber_bvfree( pnewSuperior );
431 if ( nnewSuperior != NULL ) ber_bvfree( nnewSuperior );