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"
31 #include "proto-sql.h"
34 backsql_modrdn( Operation *op, SlapReply *rs )
36 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
40 backsql_entryID e_id = BACKSQL_ENTRYID_INIT,
41 pe_id = BACKSQL_ENTRYID_INIT,
42 new_pid = BACKSQL_ENTRYID_INIT;
43 backsql_oc_map_rec *oc = NULL;
44 struct berval p_dn, p_ndn,
45 *new_pdn = NULL, *new_npdn = NULL,
47 LDAPRDN new_rdn = NULL;
48 LDAPRDN old_rdn = NULL;
51 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\n", 0, 0, 0 );
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, NULL );
178 rs->sr_err = dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn,
180 if ( rs->sr_err != LDAP_SUCCESS ) {
181 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
182 "new dn is invalid (\"%s\") - aborting\n",
183 new_dn.bv_val, 0, 0 );
184 rs->sr_text = "unable to build new DN";
185 send_ldap_result( op, rs );
189 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n",
190 new_dn.bv_val, 0, 0 );
192 rs->sr_err = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
193 if ( rs->sr_err != LDAP_SUCCESS ) {
194 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
195 "could not lookup old parent entry id\n", 0, 0, 0 );
196 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
197 ? "SQL-backend error" : NULL;
198 send_ldap_result( op, rs );
202 #ifdef BACKSQL_ARBITRARY_KEY
203 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
204 "old parent entry id is %s\n", pe_id.eid_id.bv_val, 0, 0 );
205 #else /* ! BACKSQL_ARBITRARY_KEY */
206 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
207 "old parent entry id is %ld\n", pe_id.eid_id, 0, 0 );
208 #endif /* ! BACKSQL_ARBITRARY_KEY */
210 backsql_free_entryID( &pe_id, 0 );
212 rs->sr_err = backsql_dn2id( bi, &new_pid, dbh, new_npdn );
213 if ( rs->sr_err != LDAP_SUCCESS ) {
214 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
215 "could not lookup new parent entry id\n", 0, 0, 0 );
216 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
217 ? "SQL-backend error" : NULL;
218 send_ldap_result( op, rs );
222 #ifdef BACKSQL_ARBITRARY_KEY
223 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
224 "new parent entry id=%s\n", new_pid.eid_id.bv_val, 0, 0 );
225 #else /* ! BACKSQL_ARBITRARY_KEY */
226 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
227 "new parent entry id=%ld\n", new_pid.eid_id, 0, 0 );
228 #endif /* ! BACKSQL_ARBITRARY_KEY */
231 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
232 "executing delentry_query\n", 0, 0, 0 );
233 SQLAllocStmt( dbh, &sth );
234 #ifdef BACKSQL_ARBITRARY_KEY
235 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
236 0, 0, e_id.eid_id.bv_val, 0, 0 );
237 #else /* ! BACKSQL_ARBITRARY_KEY */
238 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
239 0, 0, &e_id.eid_id, 0, 0 );
240 #endif /* ! BACKSQL_ARBITRARY_KEY */
241 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
242 if ( rc != SQL_SUCCESS ) {
243 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
244 "failed to delete record from ldap_entries\n",
246 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
247 rs->sr_err = LDAP_OTHER;
248 rs->sr_text = "SQL-backend error";
249 send_ldap_result( op, rs );
253 SQLFreeStmt( sth, SQL_RESET_PARAMS );
255 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
256 "executing insentry_query\n", 0, 0, 0 );
257 backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN );
258 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
259 0, 0, &e_id.eid_oc_id, 0, 0 );
260 #ifdef BACKSQL_ARBITRARY_KEY
261 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
262 0, 0, new_pid.eid_id.bv_val, 0, 0 );
263 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
264 0, 0, e_id.eid_keyval.bv_val, 0, 0 );
265 #else /* ! BACKSQL_ARBITRARY_KEY */
266 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
267 0, 0, &new_pid.eid_id, 0, 0 );
268 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
269 0, 0, &e_id.eid_keyval, 0, 0 );
270 #endif /* ! BACKSQL_ARBITRARY_KEY */
271 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
272 if ( rc != SQL_SUCCESS ) {
273 Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
274 "could not insert ldap_entries record\n", 0, 0, 0 );
275 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
276 rs->sr_err = LDAP_OTHER;
277 rs->sr_text = "SQL-backend error";
278 send_ldap_result( op, rs );
283 * Get attribute type and attribute value of our new rdn,
284 * we will need to add that to our new entry
286 if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn,
287 (char **)&rs->sr_text,
288 LDAP_DN_FORMAT_LDAP ) ) {
290 LDAP_LOG ( OPERATION, ERR,
291 " backsql_modrdn: can't figure out "
292 "type(s)/values(s) of newrdn\n",
295 Debug( LDAP_DEBUG_TRACE,
296 " backsql_modrdn: can't figure out "
297 "type(s)/values(s) of newrdn\n",
300 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
305 LDAP_LOG ( OPERATION, RESULTS,
306 " backsql_modrdn: new_rdn_type=\"%s\", "
307 "new_rdn_val=\"%s\"\n",
308 new_rdn[ 0 ]->la_attr.bv_val,
309 new_rdn[ 0 ]->la_value.bv_val, 0 );
311 Debug( LDAP_DEBUG_TRACE,
312 " backsql_modrdn: new_rdn_type=\"%s\", "
313 "new_rdn_val=\"%s\"\n",
314 new_rdn[ 0 ]->la_attr.bv_val,
315 new_rdn[ 0 ]->la_value.bv_val, 0 );
318 if ( op->oq_modrdn.rs_deleteoldrdn ) {
319 if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn,
320 (char **)&rs->sr_text,
321 LDAP_DN_FORMAT_LDAP ) ) {
323 LDAP_LOG ( OPERATION, ERR,
324 " backsql_modrdn: can't figure out "
325 "type(s)/values(s) of old_rdn\n",
328 Debug( LDAP_DEBUG_TRACE,
329 " backsql_modrdn: can't figure out "
330 "the old_rdn type(s)/value(s)\n",
333 rs->sr_err = LDAP_OTHER;
340 rs->sr_err = slap_modrdn2mods( op, rs, &e, old_rdn, new_rdn, &mod );
341 if ( rs->sr_err != LDAP_SUCCESS ) {
345 if ( !acl_check_modlist( op, &e, mod )) {
346 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
350 oc = backsql_id2oc( bi, e_id.eid_oc_id );
351 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod );
353 if ( rs->sr_err == LDAP_SUCCESS ) {
356 * Commit only if all operations succeed
358 SQLTransact( SQL_NULL_HENV, dbh,
359 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
363 SQLFreeStmt( sth, SQL_DROP );
365 if ( new_dn.bv_val ) {
366 ch_free( new_dn.bv_val );
369 if ( new_ndn.bv_val ) {
370 ch_free( new_ndn.bv_val );
373 /* LDAP v2 supporting correct attribute handling. */
374 if ( new_rdn != NULL ) {
375 ldap_rdnfree( new_rdn );
377 if ( old_rdn != NULL ) {
378 ldap_rdnfree( old_rdn );
382 for (; mod; mod=tmp ) {
388 if ( new_pid.eid_dn.bv_val ) {
389 backsql_free_entryID( &pe_id, 0 );
392 send_ldap_result( op, rs );
394 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
398 #endif /* SLAPD_SQL */