2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2004 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was initially developed by Dmitry Kovalev for inclusion
18 * by OpenLDAP Software.
24 #include <sys/types.h>
25 #include "ac/string.h"
28 #include "proto-sql.h"
31 backsql_modrdn( Operation *op, SlapReply *rs )
33 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
37 backsql_entryID e_id = BACKSQL_ENTRYID_INIT,
38 pe_id = BACKSQL_ENTRYID_INIT,
39 new_pe_id = BACKSQL_ENTRYID_INIT;
40 backsql_oc_map_rec *oc = NULL;
41 struct berval p_dn = BER_BVNULL, p_ndn = BER_BVNULL,
42 *new_pdn = NULL, *new_npdn = NULL,
43 new_dn = BER_BVNULL, new_ndn = BER_BVNULL,
44 realnew_dn = BER_BVNULL;
45 LDAPRDN new_rdn = NULL;
46 LDAPRDN old_rdn = NULL;
48 Modifications *mod = NULL;
49 struct berval *newSuperior = op->oq_modrdn.rs_newSup;
52 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", "
53 "newrdn=\"%s\", newSuperior=\"%s\"\n",
54 op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val,
55 newSuperior ? newSuperior->bv_val : "(NULL)" );
56 rs->sr_err = backsql_get_db_conn( op, &dbh );
57 if ( rs->sr_err != LDAP_SUCCESS ) {
58 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
59 "could not get connection handle - exiting\n",
61 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
62 ? "SQL-backend error" : NULL;
63 send_ldap_result( op, rs );
67 rs->sr_err = backsql_dn2id( op, rs, &e_id, dbh, &op->o_req_ndn, 1 );
68 if ( rs->sr_err != LDAP_SUCCESS ) {
69 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
70 "could not lookup entry id (%d)\n",
72 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
73 ? "SQL-backend error" : NULL;
74 send_ldap_result( op, rs );
78 #ifdef BACKSQL_ARBITRARY_KEY
79 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%s\n",
80 e_id.eid_id.bv_val, 0, 0 );
81 #else /* ! BACKSQL_ARBITRARY_KEY */
82 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%ld\n",
84 #endif /* ! BACKSQL_ARBITRARY_KEY */
86 if ( backsql_has_children( bi, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
87 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
88 "entry \"%s\" has children\n",
89 op->o_req_dn.bv_val, 0, 0 );
90 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
91 rs->sr_text = "subtree rename not supported";
92 send_ldap_result( op, rs );
96 dnParent( &op->o_req_dn, &p_dn );
97 dnParent( &op->o_req_ndn, &p_ndn );
100 * namingContext "" is not supported
102 if ( p_dn.bv_len == 0 ) {
103 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
104 "parent is \"\" - aborting\n", 0, 0, 0 );
105 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
106 rs->sr_text = "not allowed within namingContext";
107 send_ldap_result( op, rs );
112 * Check for children access to parent
117 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
118 NULL, ACL_WRITE, NULL ) ) {
119 Debug( LDAP_DEBUG_TRACE, " no access to parent\n", 0, 0, 0 );
120 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
126 * namingContext "" is not supported
128 if ( newSuperior->bv_len == 0 ) {
129 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
130 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
131 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
132 rs->sr_text = "not allowed within namingContext";
133 send_ldap_result( op, rs );
137 new_pdn = newSuperior;
138 new_npdn = op->oq_modrdn.rs_nnewSup;
141 e.e_nname = *new_npdn;
144 * Check for children access to new parent
146 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
147 NULL, ACL_WRITE, NULL ) ) {
148 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
149 "no access to new parent \"%s\"\n",
150 new_pdn->bv_val, 0, 0 );
151 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
160 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
161 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
162 "newSuperior is equal to old parent - ignored\n",
167 if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
168 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
169 "newSuperior is equal to entry being moved "
170 "- aborting\n", 0, 0, 0 );
171 rs->sr_err = LDAP_OTHER;
172 rs->sr_text = "newSuperior is equal to old DN";
173 send_ldap_result( op, rs );
177 build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn,
179 rs->sr_err = dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn,
181 if ( rs->sr_err != LDAP_SUCCESS ) {
182 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
183 "new dn is invalid (\"%s\") - aborting\n",
184 new_dn.bv_val, 0, 0 );
185 rs->sr_text = "unable to build new DN";
186 send_ldap_result( op, rs );
190 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n",
191 new_dn.bv_val, 0, 0 );
193 rs->sr_err = backsql_dn2id( op, rs, &pe_id, dbh, &p_ndn, 1 );
194 if ( rs->sr_err != LDAP_SUCCESS ) {
195 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
196 "could not lookup old parent entry id\n", 0, 0, 0 );
197 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
198 ? "SQL-backend error" : NULL;
199 send_ldap_result( op, rs );
203 #ifdef BACKSQL_ARBITRARY_KEY
204 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
205 "old parent entry id is %s\n", pe_id.eid_id.bv_val, 0, 0 );
206 #else /* ! BACKSQL_ARBITRARY_KEY */
207 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
208 "old parent entry id is %ld\n", pe_id.eid_id, 0, 0 );
209 #endif /* ! BACKSQL_ARBITRARY_KEY */
211 (void)backsql_free_entryID( &pe_id, 0 );
213 rs->sr_err = backsql_dn2id( op, rs, &new_pe_id, dbh, new_npdn, 1 );
214 if ( rs->sr_err != LDAP_SUCCESS ) {
215 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
216 "could not lookup new parent entry id\n", 0, 0, 0 );
217 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
218 ? "SQL-backend error" : NULL;
219 send_ldap_result( op, rs );
223 #ifdef BACKSQL_ARBITRARY_KEY
224 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
225 "new parent entry id=%s\n", new_pe_id.eid_id.bv_val, 0, 0 );
226 #else /* ! BACKSQL_ARBITRARY_KEY */
227 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
228 "new parent entry id=%ld\n", new_pe_id.eid_id, 0, 0 );
229 #endif /* ! BACKSQL_ARBITRARY_KEY */
232 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
233 "executing delentry_query\n", 0, 0, 0 );
235 rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_query, 0 );
236 if ( rc != SQL_SUCCESS ) {
237 Debug( LDAP_DEBUG_TRACE,
238 " backsql_modrdn(): "
239 "error preparing delentry_query\n", 0, 0, 0 );
240 backsql_PrintErrors( bi->sql_db_env, dbh,
243 rs->sr_text = "SQL-backend error";
244 rs->sr_err = LDAP_OTHER;
248 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
249 if ( rc != SQL_SUCCESS ) {
250 Debug( LDAP_DEBUG_TRACE,
251 " backsql_delete(): "
252 "error binding entry ID parameter "
253 "for objectClass %s\n",
254 oc->bom_oc->soc_cname.bv_val, 0, 0 );
255 backsql_PrintErrors( bi->sql_db_env, dbh,
257 SQLFreeStmt( sth, SQL_DROP );
259 rs->sr_text = "SQL-backend error";
260 rs->sr_err = LDAP_OTHER;
264 rc = SQLExecute( sth );
265 if ( rc != SQL_SUCCESS ) {
266 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
267 "failed to delete record from ldap_entries\n",
269 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
270 SQLFreeStmt( sth, SQL_DROP );
271 rs->sr_err = LDAP_OTHER;
272 rs->sr_text = "SQL-backend error";
273 send_ldap_result( op, rs );
277 SQLFreeStmt( sth, SQL_DROP );
279 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
280 "executing insentry_query\n", 0, 0, 0 );
282 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_query, 0 );
283 if ( rc != SQL_SUCCESS ) {
284 Debug( LDAP_DEBUG_TRACE,
285 " backsql_modrdn(): "
286 "error preparing insentry_query\n", 0, 0, 0 );
287 backsql_PrintErrors( bi->sql_db_env, dbh,
290 rs->sr_text = "SQL-backend error";
291 rs->sr_err = LDAP_OTHER;
296 if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) {
297 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): "
298 "backsql_api_dn2odbc(\"%s\") failed\n",
299 op->o_req_dn.bv_val, realnew_dn.bv_val, 0 );
300 SQLFreeStmt( sth, SQL_DROP );
302 rs->sr_text = "SQL-backend error";
303 rs->sr_err = LDAP_OTHER;
307 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn );
308 if ( rc != SQL_SUCCESS ) {
309 Debug( LDAP_DEBUG_TRACE,
310 " backsql_add_attr(): "
311 "error binding DN parameter for objectClass %s\n",
312 oc->bom_oc->soc_cname.bv_val, 0, 0 );
313 backsql_PrintErrors( bi->sql_db_env, dbh,
315 SQLFreeStmt( sth, SQL_DROP );
317 rs->sr_text = "SQL-backend error";
318 rs->sr_err = LDAP_OTHER;
322 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &e_id.eid_oc_id );
323 if ( rc != SQL_SUCCESS ) {
324 Debug( LDAP_DEBUG_TRACE,
325 " backsql_add_attr(): "
326 "error binding objectClass ID parameter for objectClass %s\n",
327 oc->bom_oc->soc_cname.bv_val, 0, 0 );
328 backsql_PrintErrors( bi->sql_db_env, dbh,
330 SQLFreeStmt( sth, SQL_DROP );
332 rs->sr_text = "SQL-backend error";
333 rs->sr_err = LDAP_OTHER;
337 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &new_pe_id.eid_id );
338 if ( rc != SQL_SUCCESS ) {
339 Debug( LDAP_DEBUG_TRACE,
340 " backsql_add_attr(): "
341 "error binding parent ID parameter for objectClass %s\n",
342 oc->bom_oc->soc_cname.bv_val, 0, 0 );
343 backsql_PrintErrors( bi->sql_db_env, dbh,
345 SQLFreeStmt( sth, SQL_DROP );
347 rs->sr_text = "SQL-backend error";
348 rs->sr_err = LDAP_OTHER;
352 rc = backsql_BindParamID( sth, 4, 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,
360 SQLFreeStmt( sth, SQL_DROP );
362 rs->sr_text = "SQL-backend error";
363 rs->sr_err = LDAP_OTHER;
367 rc = SQLExecute( sth );
368 if ( rc != SQL_SUCCESS ) {
369 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
370 "could not insert ldap_entries record\n", 0, 0, 0 );
371 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
372 SQLFreeStmt( sth, SQL_DROP );
373 rs->sr_err = LDAP_OTHER;
374 rs->sr_text = "SQL-backend error";
375 send_ldap_result( op, rs );
378 SQLFreeStmt( sth, SQL_DROP );
381 * Get attribute type and attribute value of our new rdn,
382 * we will need to add that to our new entry
384 if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn, &next,
385 LDAP_DN_FORMAT_LDAP ) )
387 Debug( LDAP_DEBUG_TRACE,
388 " backsql_modrdn: can't figure out "
389 "type(s)/values(s) of newrdn\n",
391 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
395 Debug( LDAP_DEBUG_TRACE,
396 " backsql_modrdn: new_rdn_type=\"%s\", "
397 "new_rdn_val=\"%s\"\n",
398 new_rdn[ 0 ]->la_attr.bv_val,
399 new_rdn[ 0 ]->la_value.bv_val, 0 );
401 if ( op->oq_modrdn.rs_deleteoldrdn ) {
402 if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn, &next,
403 LDAP_DN_FORMAT_LDAP ) )
405 Debug( LDAP_DEBUG_TRACE,
406 " backsql_modrdn: can't figure out "
407 "the old_rdn type(s)/value(s)\n",
409 rs->sr_err = LDAP_OTHER;
416 rs->sr_err = slap_modrdn2mods( op, rs, &e, old_rdn, new_rdn, &mod );
417 if ( rs->sr_err != LDAP_SUCCESS ) {
421 if ( !acl_check_modlist( op, &e, mod )) {
422 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
426 oc = backsql_id2oc( bi, e_id.eid_oc_id );
427 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod );
431 * Commit only if all operations succeed
433 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
434 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
437 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
441 if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) {
442 ch_free( realnew_dn.bv_val );
445 if ( !BER_BVISNULL( &new_dn ) ) {
446 slap_sl_free( new_dn.bv_val, op->o_tmpmemctx );
449 if ( !BER_BVISNULL( &new_ndn ) ) {
450 slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx );
453 /* LDAP v2 supporting correct attribute handling. */
454 if ( new_rdn != NULL ) {
455 ldap_rdnfree( new_rdn );
457 if ( old_rdn != NULL ) {
458 ldap_rdnfree( old_rdn );
462 for (; mod; mod = tmp ) {
468 if ( !BER_BVISNULL( &new_pe_id.eid_ndn ) ) {
469 (void)backsql_free_entryID( &new_pe_id, 0 );
472 send_ldap_result( op, rs );
474 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );