2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2005 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
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>.
18 * This work was initially developed by Dmitry Kovalev for inclusion
19 * by OpenLDAP Software. Additional significant contributors include
20 * Pierangelo Masarati.
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;
36 SQLHDBC dbh = SQL_NULL_HDBC;
37 SQLHSTMT sth = SQL_NULL_HSTMT;
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 realnew_dn = BER_BVNULL;
47 LDAPRDN new_rdn = NULL;
48 LDAPRDN old_rdn = NULL;
50 Modifications *mod = NULL;
51 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)" );
58 rs->sr_err = backsql_get_db_conn( op, &dbh );
59 if ( rs->sr_err != LDAP_SUCCESS ) {
60 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
61 "could not get connection handle - exiting\n",
63 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
64 ? "SQL-backend error" : NULL;
65 send_ldap_result( op, rs );
69 rs->sr_err = backsql_dn2id( op, rs, &e_id, dbh, &op->o_req_ndn, 1 );
70 if ( rs->sr_err != LDAP_SUCCESS ) {
71 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
72 "could not lookup entry id (%d)\n",
74 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
75 ? "SQL-backend error" : NULL;
76 send_ldap_result( op, rs );
80 #ifdef BACKSQL_ARBITRARY_KEY
81 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%s\n",
82 e_id.eid_id.bv_val, 0, 0 );
83 #else /* ! BACKSQL_ARBITRARY_KEY */
84 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%ld\n",
86 #endif /* ! BACKSQL_ARBITRARY_KEY */
88 if ( backsql_has_children( bi, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
89 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
90 "entry \"%s\" has children\n",
91 op->o_req_dn.bv_val, 0, 0 );
92 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
93 rs->sr_text = "subtree rename not supported";
94 send_ldap_result( op, rs );
98 dnParent( &op->o_req_dn, &p_dn );
99 dnParent( &op->o_req_ndn, &p_ndn );
102 * namingContext "" is not supported
104 if ( p_dn.bv_len == 0 ) {
105 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
106 "parent is \"\" - aborting\n", 0, 0, 0 );
107 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
108 rs->sr_text = "not allowed within namingContext";
109 send_ldap_result( op, rs );
114 * Check for children access to parent
119 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
120 NULL, ACL_WRITE, NULL ) ) {
121 Debug( LDAP_DEBUG_TRACE, " no access to parent\n", 0, 0, 0 );
122 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
128 * namingContext "" is not supported
130 if ( newSuperior->bv_len == 0 ) {
131 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
132 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
133 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
134 rs->sr_text = "not allowed within namingContext";
135 send_ldap_result( op, rs );
139 new_pdn = newSuperior;
140 new_npdn = op->oq_modrdn.rs_nnewSup;
143 e.e_nname = *new_npdn;
146 * Check for children access to new parent
148 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
149 NULL, ACL_WRITE, NULL ) ) {
150 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
151 "no access to new parent \"%s\"\n",
152 new_pdn->bv_val, 0, 0 );
153 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
162 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
163 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
164 "newSuperior is equal to old parent - ignored\n",
169 if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
170 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
171 "newSuperior is equal to entry being moved "
172 "- aborting\n", 0, 0, 0 );
173 rs->sr_err = LDAP_OTHER;
174 rs->sr_text = "newSuperior is equal to old DN";
175 send_ldap_result( op, rs );
179 build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn,
181 rs->sr_err = dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn,
183 if ( rs->sr_err != LDAP_SUCCESS ) {
184 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
185 "new dn is invalid (\"%s\") - aborting\n",
186 new_dn.bv_val, 0, 0 );
187 rs->sr_text = "unable to build new DN";
188 send_ldap_result( op, rs );
192 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n",
193 new_dn.bv_val, 0, 0 );
195 rs->sr_err = backsql_dn2id( op, rs, &pe_id, dbh, &p_ndn, 1 );
196 if ( rs->sr_err != LDAP_SUCCESS ) {
197 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
198 "could not lookup old parent entry id\n", 0, 0, 0 );
199 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
200 ? "SQL-backend error" : NULL;
201 send_ldap_result( op, rs );
205 #ifdef BACKSQL_ARBITRARY_KEY
206 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
207 "old parent entry id is %s\n", pe_id.eid_id.bv_val, 0, 0 );
208 #else /* ! BACKSQL_ARBITRARY_KEY */
209 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
210 "old parent entry id is %ld\n", pe_id.eid_id, 0, 0 );
211 #endif /* ! BACKSQL_ARBITRARY_KEY */
213 (void)backsql_free_entryID( &pe_id, 0 );
215 rs->sr_err = backsql_dn2id( op, rs, &new_pe_id, dbh, new_npdn, 1 );
216 if ( rs->sr_err != LDAP_SUCCESS ) {
217 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
218 "could not lookup new parent entry id\n", 0, 0, 0 );
219 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
220 ? "SQL-backend error" : NULL;
221 send_ldap_result( op, rs );
225 #ifdef BACKSQL_ARBITRARY_KEY
226 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
227 "new parent entry id=%s\n", new_pe_id.eid_id.bv_val, 0, 0 );
228 #else /* ! BACKSQL_ARBITRARY_KEY */
229 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
230 "new parent entry id=%ld\n", new_pe_id.eid_id, 0, 0 );
231 #endif /* ! BACKSQL_ARBITRARY_KEY */
234 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
235 "executing delentry_stmt\n", 0, 0, 0 );
237 rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 );
238 if ( rc != SQL_SUCCESS ) {
239 Debug( LDAP_DEBUG_TRACE,
240 " backsql_modrdn(): "
241 "error preparing delentry_stmt\n", 0, 0, 0 );
242 backsql_PrintErrors( bi->sql_db_env, dbh,
245 rs->sr_text = "SQL-backend error";
246 rs->sr_err = LDAP_OTHER;
250 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
251 if ( rc != SQL_SUCCESS ) {
252 Debug( LDAP_DEBUG_TRACE,
253 " backsql_delete(): "
254 "error binding entry ID parameter "
255 "for objectClass %s\n",
256 oc->bom_oc->soc_cname.bv_val, 0, 0 );
257 backsql_PrintErrors( bi->sql_db_env, dbh,
259 SQLFreeStmt( sth, SQL_DROP );
261 rs->sr_text = "SQL-backend error";
262 rs->sr_err = LDAP_OTHER;
266 rc = SQLExecute( sth );
267 if ( rc != SQL_SUCCESS ) {
268 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
269 "failed to delete record from ldap_entries\n",
271 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
272 SQLFreeStmt( sth, SQL_DROP );
273 rs->sr_err = LDAP_OTHER;
274 rs->sr_text = "SQL-backend error";
275 send_ldap_result( op, rs );
279 SQLFreeStmt( sth, SQL_DROP );
281 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
282 "executing insentry_stmt\n", 0, 0, 0 );
284 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
285 if ( rc != SQL_SUCCESS ) {
286 Debug( LDAP_DEBUG_TRACE,
287 " backsql_modrdn(): "
288 "error preparing insentry_stmt\n", 0, 0, 0 );
289 backsql_PrintErrors( bi->sql_db_env, dbh,
292 rs->sr_text = "SQL-backend error";
293 rs->sr_err = LDAP_OTHER;
298 if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) {
299 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): "
300 "backsql_api_dn2odbc(\"%s\") failed\n",
301 op->o_req_dn.bv_val, realnew_dn.bv_val, 0 );
302 SQLFreeStmt( sth, SQL_DROP );
304 rs->sr_text = "SQL-backend error";
305 rs->sr_err = LDAP_OTHER;
309 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn );
310 if ( rc != SQL_SUCCESS ) {
311 Debug( LDAP_DEBUG_TRACE,
312 " backsql_add_attr(): "
313 "error binding DN parameter for objectClass %s\n",
314 oc->bom_oc->soc_cname.bv_val, 0, 0 );
315 backsql_PrintErrors( bi->sql_db_env, dbh,
317 SQLFreeStmt( sth, SQL_DROP );
319 rs->sr_text = "SQL-backend error";
320 rs->sr_err = LDAP_OTHER;
324 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &e_id.eid_oc_id );
325 if ( rc != SQL_SUCCESS ) {
326 Debug( LDAP_DEBUG_TRACE,
327 " backsql_add_attr(): "
328 "error binding objectClass ID parameter for objectClass %s\n",
329 oc->bom_oc->soc_cname.bv_val, 0, 0 );
330 backsql_PrintErrors( bi->sql_db_env, dbh,
332 SQLFreeStmt( sth, SQL_DROP );
334 rs->sr_text = "SQL-backend error";
335 rs->sr_err = LDAP_OTHER;
339 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &new_pe_id.eid_id );
340 if ( rc != SQL_SUCCESS ) {
341 Debug( LDAP_DEBUG_TRACE,
342 " backsql_add_attr(): "
343 "error binding parent ID parameter for objectClass %s\n",
344 oc->bom_oc->soc_cname.bv_val, 0, 0 );
345 backsql_PrintErrors( bi->sql_db_env, dbh,
347 SQLFreeStmt( sth, SQL_DROP );
349 rs->sr_text = "SQL-backend error";
350 rs->sr_err = LDAP_OTHER;
354 rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_keyval );
355 if ( rc != SQL_SUCCESS ) {
356 Debug( LDAP_DEBUG_TRACE,
357 " backsql_add_attr(): "
358 "error binding entry ID parameter for objectClass %s\n",
359 oc->bom_oc->soc_cname.bv_val, 0, 0 );
360 backsql_PrintErrors( bi->sql_db_env, dbh,
362 SQLFreeStmt( sth, SQL_DROP );
364 rs->sr_text = "SQL-backend error";
365 rs->sr_err = LDAP_OTHER;
369 rc = SQLExecute( sth );
370 if ( rc != SQL_SUCCESS ) {
371 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
372 "could not insert ldap_entries record\n", 0, 0, 0 );
373 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
374 SQLFreeStmt( sth, SQL_DROP );
375 rs->sr_err = LDAP_OTHER;
376 rs->sr_text = "SQL-backend error";
377 send_ldap_result( op, rs );
380 SQLFreeStmt( sth, SQL_DROP );
383 * Get attribute type and attribute value of our new rdn,
384 * we will need to add that to our new entry
386 if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn, &next,
387 LDAP_DN_FORMAT_LDAP ) )
389 Debug( LDAP_DEBUG_TRACE,
390 " backsql_modrdn: can't figure out "
391 "type(s)/values(s) of newrdn\n",
393 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
397 Debug( LDAP_DEBUG_TRACE,
398 " backsql_modrdn: new_rdn_type=\"%s\", "
399 "new_rdn_val=\"%s\"\n",
400 new_rdn[ 0 ]->la_attr.bv_val,
401 new_rdn[ 0 ]->la_value.bv_val, 0 );
403 if ( op->oq_modrdn.rs_deleteoldrdn ) {
404 if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn, &next,
405 LDAP_DN_FORMAT_LDAP ) )
407 Debug( LDAP_DEBUG_TRACE,
408 " backsql_modrdn: can't figure out "
409 "the old_rdn type(s)/value(s)\n",
411 rs->sr_err = LDAP_OTHER;
418 rs->sr_err = slap_modrdn2mods( op, rs, &e, old_rdn, new_rdn, &mod );
419 if ( rs->sr_err != LDAP_SUCCESS ) {
423 if ( !acl_check_modlist( op, &e, mod )) {
424 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
428 oc = backsql_id2oc( bi, e_id.eid_oc_id );
429 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod );
433 * Commit only if all operations succeed
435 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
436 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
439 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
443 if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) {
444 ch_free( realnew_dn.bv_val );
447 if ( !BER_BVISNULL( &new_dn ) ) {
448 slap_sl_free( new_dn.bv_val, op->o_tmpmemctx );
451 if ( !BER_BVISNULL( &new_ndn ) ) {
452 slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx );
455 /* LDAP v2 supporting correct attribute handling. */
456 if ( new_rdn != NULL ) {
457 ldap_rdnfree( new_rdn );
459 if ( old_rdn != NULL ) {
460 ldap_rdnfree( old_rdn );
464 for (; mod; mod = tmp ) {
470 if ( !BER_BVISNULL( &new_pe_id.eid_ndn ) ) {
471 (void)backsql_free_entryID( &new_pe_id, 0 );
474 send_ldap_result( op, rs );
476 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );