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.
26 #include <sys/types.h>
27 #include "ac/string.h"
30 #include "proto-sql.h"
33 backsql_modrdn( Operation *op, SlapReply *rs )
35 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
39 backsql_entryID e_id = BACKSQL_ENTRYID_INIT,
40 pe_id = BACKSQL_ENTRYID_INIT,
41 new_pe_id = BACKSQL_ENTRYID_INIT;
42 backsql_oc_map_rec *oc = NULL;
43 struct berval p_dn = BER_BVNULL, p_ndn = BER_BVNULL,
44 *new_pdn = NULL, *new_npdn = NULL,
45 new_dn = BER_BVNULL, new_ndn = BER_BVNULL;
46 LDAPRDN new_rdn = NULL;
47 LDAPRDN old_rdn = NULL;
49 Modifications *mod = NULL;
50 struct berval *newSuperior = op->oq_modrdn.rs_newSup;
53 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", "
54 "newrdn=\"%s\", newSuperior=\"%s\"\n",
55 op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val,
56 newSuperior ? newSuperior->bv_val : "(NULL)" );
57 rs->sr_err = backsql_get_db_conn( op, &dbh );
58 if ( rs->sr_err != LDAP_SUCCESS ) {
59 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
60 "could not get connection handle - exiting\n",
62 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
63 ? "SQL-backend error" : NULL;
64 send_ldap_result( op, rs );
68 rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn );
69 if ( rs->sr_err != LDAP_SUCCESS ) {
70 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
71 "could not lookup entry id (%d)\n",
73 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
74 ? "SQL-backend error" : NULL;
75 send_ldap_result( op, rs );
79 #ifdef BACKSQL_ARBITRARY_KEY
80 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%s\n",
81 e_id.eid_id.bv_val, 0, 0 );
82 #else /* ! BACKSQL_ARBITRARY_KEY */
83 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%ld\n",
85 #endif /* ! BACKSQL_ARBITRARY_KEY */
87 if ( backsql_has_children( bi, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
88 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
89 "entry \"%s\" has children\n",
90 op->o_req_dn.bv_val, 0, 0 );
91 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
92 rs->sr_text = "subtree rename not supported";
93 send_ldap_result( op, rs );
97 dnParent( &op->o_req_dn, &p_dn );
98 dnParent( &op->o_req_ndn, &p_ndn );
101 * namingContext "" is not supported
103 if ( p_dn.bv_len == 0 ) {
104 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
105 "parent is \"\" - aborting\n", 0, 0, 0 );
106 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
107 rs->sr_text = "not allowed within namingContext";
108 send_ldap_result( op, rs );
113 * Check for children access to parent
118 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
119 NULL, ACL_WRITE, NULL ) ) {
120 Debug( LDAP_DEBUG_TRACE, " no access to parent\n", 0, 0, 0 );
121 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
127 * namingContext "" is not supported
129 if ( newSuperior->bv_len == 0 ) {
130 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
131 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
132 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
133 rs->sr_text = "not allowed within namingContext";
134 send_ldap_result( op, rs );
138 new_pdn = newSuperior;
139 new_npdn = op->oq_modrdn.rs_nnewSup;
142 e.e_nname = *new_npdn;
145 * Check for children access to new parent
147 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
148 NULL, ACL_WRITE, NULL ) ) {
149 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
150 "no access to new parent \"%s\"\n",
151 new_pdn->bv_val, 0, 0 );
152 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
161 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
162 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
163 "newSuperior is equal to old parent - ignored\n",
168 if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
169 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
170 "newSuperior is equal to entry being moved "
171 "- aborting\n", 0, 0, 0 );
172 rs->sr_err = LDAP_OTHER;
173 rs->sr_text = "newSuperior is equal to old DN";
174 send_ldap_result( op, rs );
178 build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn,
180 rs->sr_err = dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn,
182 if ( rs->sr_err != LDAP_SUCCESS ) {
183 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
184 "new dn is invalid (\"%s\") - aborting\n",
185 new_dn.bv_val, 0, 0 );
186 rs->sr_text = "unable to build new DN";
187 send_ldap_result( op, rs );
191 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n",
192 new_dn.bv_val, 0, 0 );
194 rs->sr_err = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
195 if ( rs->sr_err != LDAP_SUCCESS ) {
196 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
197 "could not lookup old parent entry id\n", 0, 0, 0 );
198 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
199 ? "SQL-backend error" : NULL;
200 send_ldap_result( op, rs );
204 #ifdef BACKSQL_ARBITRARY_KEY
205 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
206 "old parent entry id is %s\n", pe_id.eid_id.bv_val, 0, 0 );
207 #else /* ! BACKSQL_ARBITRARY_KEY */
208 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
209 "old parent entry id is %ld\n", pe_id.eid_id, 0, 0 );
210 #endif /* ! BACKSQL_ARBITRARY_KEY */
212 (void)backsql_free_entryID( &pe_id, 0 );
214 rs->sr_err = backsql_dn2id( bi, &new_pe_id, dbh, new_npdn );
215 if ( rs->sr_err != LDAP_SUCCESS ) {
216 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
217 "could not lookup new parent entry id\n", 0, 0, 0 );
218 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
219 ? "SQL-backend error" : NULL;
220 send_ldap_result( op, rs );
224 #ifdef BACKSQL_ARBITRARY_KEY
225 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
226 "new parent entry id=%s\n", new_pe_id.eid_id.bv_val, 0, 0 );
227 #else /* ! BACKSQL_ARBITRARY_KEY */
228 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
229 "new parent entry id=%ld\n", new_pe_id.eid_id, 0, 0 );
230 #endif /* ! BACKSQL_ARBITRARY_KEY */
233 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
234 "executing delentry_query\n", 0, 0, 0 );
236 rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_query, 0 );
237 if ( rc != SQL_SUCCESS ) {
238 Debug( LDAP_DEBUG_TRACE,
239 " backsql_modrdn(): "
240 "error preparing delentry_query\n", 0, 0, 0 );
241 backsql_PrintErrors( bi->sql_db_env, dbh,
244 rs->sr_text = "SQL-backend error";
245 rs->sr_err = LDAP_OTHER;
249 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
250 if ( rc != SQL_SUCCESS ) {
251 Debug( LDAP_DEBUG_TRACE,
252 " backsql_delete(): "
253 "error binding entry ID parameter "
254 "for objectClass %s\n",
255 oc->bom_oc->soc_cname.bv_val, 0, 0 );
256 backsql_PrintErrors( bi->sql_db_env, dbh,
258 SQLFreeStmt( sth, SQL_DROP );
260 rs->sr_text = "SQL-backend error";
261 rs->sr_err = LDAP_OTHER;
265 rc = SQLExecute( sth );
266 if ( rc != SQL_SUCCESS ) {
267 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
268 "failed to delete record from ldap_entries\n",
270 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
271 SQLFreeStmt( sth, SQL_DROP );
272 rs->sr_err = LDAP_OTHER;
273 rs->sr_text = "SQL-backend error";
274 send_ldap_result( op, rs );
278 SQLFreeStmt( sth, SQL_DROP );
280 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
281 "executing insentry_query\n", 0, 0, 0 );
283 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_query, 0 );
284 if ( rc != SQL_SUCCESS ) {
285 Debug( LDAP_DEBUG_TRACE,
286 " backsql_modrdn(): "
287 "error preparing insentry_query\n", 0, 0, 0 );
288 backsql_PrintErrors( bi->sql_db_env, dbh,
291 rs->sr_text = "SQL-backend error";
292 rs->sr_err = LDAP_OTHER;
296 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &new_dn );
297 if ( rc != SQL_SUCCESS ) {
298 Debug( LDAP_DEBUG_TRACE,
299 " backsql_add_attr(): "
300 "error binding DN parameter for objectClass %s\n",
301 oc->bom_oc->soc_cname.bv_val, 0, 0 );
302 backsql_PrintErrors( bi->sql_db_env, dbh,
304 SQLFreeStmt( sth, SQL_DROP );
306 rs->sr_text = "SQL-backend error";
307 rs->sr_err = LDAP_OTHER;
311 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &e_id.eid_oc_id );
312 if ( rc != SQL_SUCCESS ) {
313 Debug( LDAP_DEBUG_TRACE,
314 " backsql_add_attr(): "
315 "error binding objectClass ID parameter for objectClass %s\n",
316 oc->bom_oc->soc_cname.bv_val, 0, 0 );
317 backsql_PrintErrors( bi->sql_db_env, dbh,
319 SQLFreeStmt( sth, SQL_DROP );
321 rs->sr_text = "SQL-backend error";
322 rs->sr_err = LDAP_OTHER;
326 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &new_pe_id.eid_id );
327 if ( rc != SQL_SUCCESS ) {
328 Debug( LDAP_DEBUG_TRACE,
329 " backsql_add_attr(): "
330 "error binding parent ID parameter for objectClass %s\n",
331 oc->bom_oc->soc_cname.bv_val, 0, 0 );
332 backsql_PrintErrors( bi->sql_db_env, dbh,
334 SQLFreeStmt( sth, SQL_DROP );
336 rs->sr_text = "SQL-backend error";
337 rs->sr_err = LDAP_OTHER;
341 rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_keyval );
342 if ( rc != SQL_SUCCESS ) {
343 Debug( LDAP_DEBUG_TRACE,
344 " backsql_add_attr(): "
345 "error binding entry ID parameter for objectClass %s\n",
346 oc->bom_oc->soc_cname.bv_val, 0, 0 );
347 backsql_PrintErrors( bi->sql_db_env, dbh,
349 SQLFreeStmt( sth, SQL_DROP );
351 rs->sr_text = "SQL-backend error";
352 rs->sr_err = LDAP_OTHER;
356 rc = SQLExecute( sth );
357 if ( rc != SQL_SUCCESS ) {
358 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
359 "could not insert ldap_entries record\n", 0, 0, 0 );
360 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
361 SQLFreeStmt( sth, SQL_DROP );
362 rs->sr_err = LDAP_OTHER;
363 rs->sr_text = "SQL-backend error";
364 send_ldap_result( op, rs );
367 SQLFreeStmt( sth, SQL_DROP );
370 * Get attribute type and attribute value of our new rdn,
371 * we will need to add that to our new entry
373 if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn, &next,
374 LDAP_DN_FORMAT_LDAP ) )
376 Debug( LDAP_DEBUG_TRACE,
377 " backsql_modrdn: can't figure out "
378 "type(s)/values(s) of newrdn\n",
380 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
384 Debug( LDAP_DEBUG_TRACE,
385 " backsql_modrdn: new_rdn_type=\"%s\", "
386 "new_rdn_val=\"%s\"\n",
387 new_rdn[ 0 ]->la_attr.bv_val,
388 new_rdn[ 0 ]->la_value.bv_val, 0 );
390 if ( op->oq_modrdn.rs_deleteoldrdn ) {
391 if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn, &next,
392 LDAP_DN_FORMAT_LDAP ) )
394 Debug( LDAP_DEBUG_TRACE,
395 " backsql_modrdn: can't figure out "
396 "the old_rdn type(s)/value(s)\n",
398 rs->sr_err = LDAP_OTHER;
405 rs->sr_err = slap_modrdn2mods( op, rs, &e, old_rdn, new_rdn, &mod );
406 if ( rs->sr_err != LDAP_SUCCESS ) {
410 if ( !acl_check_modlist( op, &e, mod )) {
411 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
415 oc = backsql_id2oc( bi, e_id.eid_oc_id );
416 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod );
420 * Commit only if all operations succeed
422 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
423 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
426 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
430 if ( !BER_BVISNULL( &new_dn ) ) {
431 slap_sl_free( new_dn.bv_val, op->o_tmpmemctx );
434 if ( !BER_BVISNULL( &new_ndn ) ) {
435 slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx );
438 /* LDAP v2 supporting correct attribute handling. */
439 if ( new_rdn != NULL ) {
440 ldap_rdnfree( new_rdn );
442 if ( old_rdn != NULL ) {
443 ldap_rdnfree( old_rdn );
447 for (; mod; mod = tmp ) {
453 if ( new_pe_id.eid_dn.bv_val ) {
454 (void)backsql_free_entryID( &new_pe_id, 0 );
457 send_ldap_result( op, rs );
459 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
463 #endif /* SLAPD_SQL */