Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / openldap / dist / servers / slapd / back-sql / modrdn.c
blob62ef2c36ff7ae1b2a7a964e73679b4a3e60ad351
1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-sql/modrdn.c,v 1.39.2.5 2008/02/11 23:26:48 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2008 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
17 /* ACKNOWLEDGEMENTS:
18 * This work was initially developed by Dmitry Kovalev for inclusion
19 * by OpenLDAP Software. Additional significant contributors include
20 * Pierangelo Masarati.
23 #include "portable.h"
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include "ac/string.h"
29 #include "slap.h"
30 #include "proto-sql.h"
32 int
33 backsql_modrdn( Operation *op, SlapReply *rs )
35 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
36 SQLHDBC dbh = SQL_NULL_HDBC;
37 SQLHSTMT sth = SQL_NULL_HSTMT;
38 RETCODE rc;
39 backsql_entryID e_id = BACKSQL_ENTRYID_INIT,
40 n_id = BACKSQL_ENTRYID_INIT;
41 backsql_srch_info bsi = { 0 };
42 backsql_oc_map_rec *oc = NULL;
43 struct berval pdn = BER_BVNULL, pndn = BER_BVNULL,
44 *new_pdn = NULL, *new_npdn = NULL,
45 new_dn = BER_BVNULL, new_ndn = BER_BVNULL,
46 realnew_dn = BER_BVNULL;
47 Entry r = { 0 },
48 p = { 0 },
49 n = { 0 },
50 *e = NULL;
51 int manageDSAit = get_manageDSAit( op );
52 struct berval *newSuperior = op->oq_modrdn.rs_newSup;
54 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", "
55 "newrdn=\"%s\", newSuperior=\"%s\"\n",
56 op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val,
57 newSuperior ? newSuperior->bv_val : "(NULL)" );
59 rs->sr_err = backsql_get_db_conn( op, &dbh );
60 if ( rs->sr_err != LDAP_SUCCESS ) {
61 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
62 "could not get connection handle - exiting\n",
63 0, 0, 0 );
64 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
65 ? "SQL-backend error" : NULL;
66 e = NULL;
67 goto done;
70 bsi.bsi_e = &r;
71 rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
72 LDAP_SCOPE_BASE,
73 (time_t)(-1), NULL, dbh, op, rs,
74 slap_anlist_all_attributes,
75 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
76 switch ( rs->sr_err ) {
77 case LDAP_SUCCESS:
78 break;
80 case LDAP_REFERRAL:
81 if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
82 dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
84 rs->sr_err = LDAP_SUCCESS;
85 rs->sr_text = NULL;
86 rs->sr_matched = NULL;
87 if ( rs->sr_ref ) {
88 ber_bvarray_free( rs->sr_ref );
89 rs->sr_ref = NULL;
91 break;
93 e = &r;
94 /* fallthru */
96 default:
97 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
98 "could not retrieve modrdnDN ID - no such entry\n",
99 0, 0, 0 );
100 if ( !BER_BVISNULL( &r.e_nname ) ) {
101 /* FIXME: should always be true! */
102 e = &r;
104 } else {
105 e = NULL;
107 goto done;
110 #ifdef BACKSQL_ARBITRARY_KEY
111 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%s\n",
112 e_id.eid_id.bv_val, 0, 0 );
113 #else /* ! BACKSQL_ARBITRARY_KEY */
114 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%ld\n",
115 e_id.eid_id, 0, 0 );
116 #endif /* ! BACKSQL_ARBITRARY_KEY */
118 if ( get_assert( op ) &&
119 ( test_filter( op, &r, get_assertion( op ) )
120 != LDAP_COMPARE_TRUE ) )
122 rs->sr_err = LDAP_ASSERTION_FAILED;
123 e = &r;
124 goto done;
127 if ( backsql_has_children( op, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
128 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
129 "entry \"%s\" has children\n",
130 op->o_req_dn.bv_val, 0, 0 );
131 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
132 rs->sr_text = "subtree rename not supported";
133 e = &r;
134 goto done;
138 * Check for entry access to target
140 if ( !access_allowed( op, &r, slap_schema.si_ad_entry,
141 NULL, ACL_WRITE, NULL ) ) {
142 Debug( LDAP_DEBUG_TRACE, " no access to entry\n", 0, 0, 0 );
143 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
144 goto done;
147 dnParent( &op->o_req_dn, &pdn );
148 dnParent( &op->o_req_ndn, &pndn );
151 * namingContext "" is not supported
153 if ( BER_BVISEMPTY( &pdn ) ) {
154 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
155 "parent is \"\" - aborting\n", 0, 0, 0 );
156 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
157 rs->sr_text = "not allowed within namingContext";
158 e = NULL;
159 goto done;
163 * Check for children access to parent
165 bsi.bsi_e = &p;
166 e_id = bsi.bsi_base_id;
167 memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
168 rs->sr_err = backsql_init_search( &bsi, &pndn,
169 LDAP_SCOPE_BASE,
170 (time_t)(-1), NULL, dbh, op, rs,
171 slap_anlist_all_attributes,
172 BACKSQL_ISF_GET_ENTRY );
174 #ifdef BACKSQL_ARBITRARY_KEY
175 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
176 "old parent entry id is %s\n",
177 bsi.bsi_base_id.eid_id.bv_val, 0, 0 );
178 #else /* ! BACKSQL_ARBITRARY_KEY */
179 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
180 "old parent entry id is %ld\n",
181 bsi.bsi_base_id.eid_id, 0, 0 );
182 #endif /* ! BACKSQL_ARBITRARY_KEY */
184 if ( rs->sr_err != LDAP_SUCCESS ) {
185 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
186 "could not retrieve renameDN ID - no such entry\n",
187 0, 0, 0 );
188 e = &p;
189 goto done;
192 if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL,
193 newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) )
195 Debug( LDAP_DEBUG_TRACE, " no access to parent\n", 0, 0, 0 );
196 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
197 goto done;
200 if ( newSuperior ) {
201 (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
204 * namingContext "" is not supported
206 if ( BER_BVISEMPTY( newSuperior ) ) {
207 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
208 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
209 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
210 rs->sr_text = "not allowed within namingContext";
211 e = NULL;
212 goto done;
215 new_pdn = newSuperior;
216 new_npdn = op->oq_modrdn.rs_nnewSup;
219 * Check for children access to new parent
221 bsi.bsi_e = &n;
222 rs->sr_err = backsql_init_search( &bsi, new_npdn,
223 LDAP_SCOPE_BASE,
224 (time_t)(-1), NULL, dbh, op, rs,
225 slap_anlist_all_attributes,
226 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
227 if ( rs->sr_err != LDAP_SUCCESS ) {
228 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
229 "could not retrieve renameDN ID - no such entry\n",
230 0, 0, 0 );
231 e = &n;
232 goto done;
235 n_id = bsi.bsi_base_id;
237 #ifdef BACKSQL_ARBITRARY_KEY
238 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
239 "new parent entry id=%s\n",
240 n_id.eid_id.bv_val, 0, 0 );
241 #else /* ! BACKSQL_ARBITRARY_KEY */
242 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
243 "new parent entry id=%ld\n",
244 n_id.eid_id, 0, 0 );
245 #endif /* ! BACKSQL_ARBITRARY_KEY */
247 if ( !access_allowed( op, &n, slap_schema.si_ad_children,
248 NULL, ACL_WADD, NULL ) ) {
249 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
250 "no access to new parent \"%s\"\n",
251 new_pdn->bv_val, 0, 0 );
252 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
253 e = &n;
254 goto done;
257 } else {
258 n_id = bsi.bsi_base_id;
259 new_pdn = &pdn;
260 new_npdn = &pndn;
263 memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
265 if ( newSuperior && dn_match( &pndn, new_npdn ) ) {
266 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
267 "newSuperior is equal to old parent - ignored\n",
268 0, 0, 0 );
269 newSuperior = NULL;
272 if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
273 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
274 "newSuperior is equal to entry being moved "
275 "- aborting\n", 0, 0, 0 );
276 rs->sr_err = LDAP_OTHER;
277 rs->sr_text = "newSuperior is equal to old DN";
278 e = &r;
279 goto done;
282 build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn,
283 op->o_tmpmemctx );
284 build_new_dn( &new_ndn, new_npdn, &op->oq_modrdn.rs_nnewrdn,
285 op->o_tmpmemctx );
287 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n",
288 new_dn.bv_val, 0, 0 );
290 realnew_dn = new_dn;
291 if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) {
292 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): "
293 "backsql_api_dn2odbc(\"%s\") failed\n",
294 op->o_req_dn.bv_val, realnew_dn.bv_val, 0 );
295 SQLFreeStmt( sth, SQL_DROP );
297 rs->sr_text = "SQL-backend error";
298 rs->sr_err = LDAP_OTHER;
299 e = NULL;
300 goto done;
303 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
304 "executing renentry_stmt\n", 0, 0, 0 );
306 rc = backsql_Prepare( dbh, &sth, bi->sql_renentry_stmt, 0 );
307 if ( rc != SQL_SUCCESS ) {
308 Debug( LDAP_DEBUG_TRACE,
309 " backsql_modrdn(): "
310 "error preparing renentry_stmt\n", 0, 0, 0 );
311 backsql_PrintErrors( bi->sql_db_env, dbh,
312 sth, rc );
314 rs->sr_text = "SQL-backend error";
315 rs->sr_err = LDAP_OTHER;
316 e = NULL;
317 goto done;
320 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn );
321 if ( rc != SQL_SUCCESS ) {
322 Debug( LDAP_DEBUG_TRACE,
323 " backsql_add_attr(): "
324 "error binding DN parameter for objectClass %s\n",
325 oc->bom_oc->soc_cname.bv_val, 0, 0 );
326 backsql_PrintErrors( bi->sql_db_env, dbh,
327 sth, rc );
328 SQLFreeStmt( sth, SQL_DROP );
330 rs->sr_text = "SQL-backend error";
331 rs->sr_err = LDAP_OTHER;
332 e = NULL;
333 goto done;
336 rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &n_id.eid_id );
337 if ( rc != SQL_SUCCESS ) {
338 Debug( LDAP_DEBUG_TRACE,
339 " backsql_add_attr(): "
340 "error binding parent ID parameter for objectClass %s\n",
341 oc->bom_oc->soc_cname.bv_val, 0, 0 );
342 backsql_PrintErrors( bi->sql_db_env, dbh,
343 sth, rc );
344 SQLFreeStmt( sth, SQL_DROP );
346 rs->sr_text = "SQL-backend error";
347 rs->sr_err = LDAP_OTHER;
348 e = NULL;
349 goto done;
352 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &e_id.eid_keyval );
353 if ( rc != SQL_SUCCESS ) {
354 Debug( LDAP_DEBUG_TRACE,
355 " backsql_add_attr(): "
356 "error binding entry ID parameter for objectClass %s\n",
357 oc->bom_oc->soc_cname.bv_val, 0, 0 );
358 backsql_PrintErrors( bi->sql_db_env, dbh,
359 sth, rc );
360 SQLFreeStmt( sth, SQL_DROP );
362 rs->sr_text = "SQL-backend error";
363 rs->sr_err = LDAP_OTHER;
364 e = NULL;
365 goto done;
368 rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_id );
369 if ( rc != SQL_SUCCESS ) {
370 Debug( LDAP_DEBUG_TRACE,
371 " backsql_add_attr(): "
372 "error binding ID parameter for objectClass %s\n",
373 oc->bom_oc->soc_cname.bv_val, 0, 0 );
374 backsql_PrintErrors( bi->sql_db_env, dbh,
375 sth, rc );
376 SQLFreeStmt( sth, SQL_DROP );
378 rs->sr_text = "SQL-backend error";
379 rs->sr_err = LDAP_OTHER;
380 e = NULL;
381 goto done;
384 rc = SQLExecute( sth );
385 if ( rc != SQL_SUCCESS ) {
386 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
387 "could not rename ldap_entries record\n", 0, 0, 0 );
388 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
389 SQLFreeStmt( sth, SQL_DROP );
390 rs->sr_err = LDAP_OTHER;
391 rs->sr_text = "SQL-backend error";
392 e = NULL;
393 goto done;
395 SQLFreeStmt( sth, SQL_DROP );
397 assert( op->orr_modlist != NULL );
399 slap_mods_opattrs( op, &op->orr_modlist, 1 );
401 assert( e_id.eid_oc != NULL );
402 oc = e_id.eid_oc;
403 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist );
404 slap_graduate_commit_csn( op );
405 if ( rs->sr_err != LDAP_SUCCESS ) {
406 e = &r;
407 goto done;
410 if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
411 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
413 backsql_entry_clean( op, &r );
414 (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
416 bsi.bsi_e = &r;
417 rs->sr_err = backsql_init_search( &bsi, &new_ndn,
418 LDAP_SCOPE_BASE,
419 (time_t)(-1), NULL, dbh, op, rs,
420 slap_anlist_all_attributes,
421 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
422 switch ( rs->sr_err ) {
423 case LDAP_SUCCESS:
424 break;
426 case LDAP_REFERRAL:
427 if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
428 dn_match( &new_ndn, &bsi.bsi_e->e_nname ) )
430 rs->sr_err = LDAP_SUCCESS;
431 rs->sr_text = NULL;
432 rs->sr_matched = NULL;
433 if ( rs->sr_ref ) {
434 ber_bvarray_free( rs->sr_ref );
435 rs->sr_ref = NULL;
437 break;
439 e = &r;
440 /* fallthru */
442 default:
443 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
444 "could not retrieve modrdnDN ID - no such entry\n",
445 0, 0, 0 );
446 if ( !BER_BVISNULL( &r.e_nname ) ) {
447 /* FIXME: should always be true! */
448 e = &r;
450 } else {
451 e = NULL;
453 goto done;
456 e_id = bsi.bsi_base_id;
458 rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0,
459 &rs->sr_text, textbuf, sizeof( textbuf ) );
460 if ( rs->sr_err != LDAP_SUCCESS ) {
461 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): "
462 "entry failed schema check -- aborting\n",
463 r.e_name.bv_val, 0, 0 );
464 e = NULL;
465 goto done;
469 done:;
470 if ( e != NULL ) {
471 if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
472 ACL_DISCLOSE, NULL ) )
474 rs->sr_err = LDAP_NO_SUCH_OBJECT;
475 rs->sr_text = NULL;
476 rs->sr_matched = NULL;
477 if ( rs->sr_ref ) {
478 ber_bvarray_free( rs->sr_ref );
479 rs->sr_ref = NULL;
485 * Commit only if all operations succeed
487 if ( sth != SQL_NULL_HSTMT ) {
488 SQLUSMALLINT CompletionType = SQL_ROLLBACK;
490 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
491 CompletionType = SQL_COMMIT;
494 SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
497 if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
498 rs->sr_err = LDAP_X_NO_OPERATION;
501 send_ldap_result( op, rs );
502 slap_graduate_commit_csn( op );
504 if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) {
505 ch_free( realnew_dn.bv_val );
508 if ( !BER_BVISNULL( &new_dn ) ) {
509 slap_sl_free( new_dn.bv_val, op->o_tmpmemctx );
512 if ( !BER_BVISNULL( &new_ndn ) ) {
513 slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx );
516 if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
517 (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
520 if ( !BER_BVISNULL( &n_id.eid_ndn ) ) {
521 (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx );
524 if ( !BER_BVISNULL( &r.e_nname ) ) {
525 backsql_entry_clean( op, &r );
528 if ( !BER_BVISNULL( &p.e_nname ) ) {
529 backsql_entry_clean( op, &p );
532 if ( !BER_BVISNULL( &n.e_nname ) ) {
533 backsql_entry_clean( op, &n );
536 if ( rs->sr_ref ) {
537 ber_bvarray_free( rs->sr_ref );
538 rs->sr_ref = NULL;
541 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
543 return rs->sr_err;