Back to index

openldap  2.4.31
modrdn.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1999-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 1999 Dmitry Kovalev.
00006  * Portions Copyright 2002 Pierangelo Masarati.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Dmitry Kovalev for inclusion
00019  * by OpenLDAP Software.  Additional significant contributors include
00020  * Pierangelo Masarati.
00021  */
00022 
00023 #include "portable.h"
00024 
00025 #include <stdio.h>
00026 #include <sys/types.h>
00027 #include "ac/string.h"
00028 
00029 #include "slap.h"
00030 #include "proto-sql.h"
00031 
00032 int
00033 backsql_modrdn( Operation *op, SlapReply *rs )
00034 {
00035        backsql_info         *bi = (backsql_info*)op->o_bd->be_private;
00036        SQLHDBC                     dbh = SQL_NULL_HDBC;
00037        SQLHSTMT             sth = SQL_NULL_HSTMT;
00038        RETCODE                     rc;
00039        backsql_entryID             e_id = BACKSQL_ENTRYID_INIT,
00040                             n_id = BACKSQL_ENTRYID_INIT;
00041        backsql_srch_info    bsi = { 0 };
00042        backsql_oc_map_rec   *oc = NULL;
00043        struct berval        pdn = BER_BVNULL, pndn = BER_BVNULL,
00044                             *new_pdn = NULL, *new_npdn = NULL,
00045                             new_dn = BER_BVNULL, new_ndn = BER_BVNULL,
00046                             realnew_dn = BER_BVNULL;
00047        Entry                r = { 0 },
00048                             p = { 0 },
00049                             n = { 0 },
00050                             *e = NULL;
00051        int                  manageDSAit = get_manageDSAit( op );
00052        struct berval        *newSuperior = op->oq_modrdn.rs_newSup;
00053  
00054        Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", "
00055                      "newrdn=\"%s\", newSuperior=\"%s\"\n",
00056                      op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val, 
00057                      newSuperior ? newSuperior->bv_val : "(NULL)" );
00058 
00059        rs->sr_err = backsql_get_db_conn( op, &dbh );
00060        if ( rs->sr_err != LDAP_SUCCESS ) {
00061               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00062                      "could not get connection handle - exiting\n", 
00063                      0, 0, 0 );
00064               rs->sr_text = ( rs->sr_err == LDAP_OTHER )
00065                      ?  "SQL-backend error" : NULL;
00066               e = NULL;
00067               goto done;
00068        }
00069 
00070        bsi.bsi_e = &r;
00071        rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
00072                      LDAP_SCOPE_BASE, 
00073                      (time_t)(-1), NULL, dbh, op, rs,
00074                      slap_anlist_all_attributes,
00075                      ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
00076        switch ( rs->sr_err ) {
00077        case LDAP_SUCCESS:
00078               break;
00079 
00080        case LDAP_REFERRAL:
00081               if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
00082                             dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
00083               {
00084                      rs->sr_err = LDAP_SUCCESS;
00085                      rs->sr_text = NULL;
00086                      rs->sr_matched = NULL;
00087                      if ( rs->sr_ref ) {
00088                             ber_bvarray_free( rs->sr_ref );
00089                             rs->sr_ref = NULL;
00090                      }
00091                      break;
00092               }
00093               e = &r;
00094               /* fallthru */
00095 
00096        default:
00097               Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
00098                      "could not retrieve modrdnDN ID - no such entry\n", 
00099                      0, 0, 0 );
00100               if ( !BER_BVISNULL( &r.e_nname ) ) {
00101                      /* FIXME: should always be true! */
00102                      e = &r;
00103 
00104               } else {
00105                      e = NULL;
00106               }
00107               goto done;
00108        }
00109 
00110        Debug( LDAP_DEBUG_TRACE,
00111               "   backsql_modrdn(): entry id=" BACKSQL_IDFMT "\n",
00112               BACKSQL_IDARG(e_id.eid_id), 0, 0 );
00113 
00114        if ( get_assert( op ) &&
00115                      ( test_filter( op, &r, get_assertion( op ) )
00116                        != LDAP_COMPARE_TRUE ) )
00117        {
00118               rs->sr_err = LDAP_ASSERTION_FAILED;
00119               e = &r;
00120               goto done;
00121        }
00122 
00123        if ( backsql_has_children( op, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
00124               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00125                      "entry \"%s\" has children\n",
00126                      op->o_req_dn.bv_val, 0, 0 );
00127               rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
00128               rs->sr_text = "subtree rename not supported";
00129               e = &r;
00130               goto done;
00131        }
00132 
00133        /*
00134         * Check for entry access to target
00135         */
00136        if ( !access_allowed( op, &r, slap_schema.si_ad_entry, 
00137                             NULL, ACL_WRITE, NULL ) ) {
00138               Debug( LDAP_DEBUG_TRACE, "   no access to entry\n", 0, 0, 0 );
00139               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
00140               goto done;
00141        }
00142 
00143        dnParent( &op->o_req_dn, &pdn );
00144        dnParent( &op->o_req_ndn, &pndn );
00145 
00146        /*
00147         * namingContext "" is not supported
00148         */
00149        if ( BER_BVISEMPTY( &pdn ) ) {
00150               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00151                      "parent is \"\" - aborting\n", 0, 0, 0 );
00152               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
00153               rs->sr_text = "not allowed within namingContext";
00154               e = NULL;
00155               goto done;
00156        }
00157 
00158        /*
00159         * Check for children access to parent
00160         */
00161        bsi.bsi_e = &p;
00162        e_id = bsi.bsi_base_id;
00163        memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
00164        rs->sr_err = backsql_init_search( &bsi, &pndn,
00165                      LDAP_SCOPE_BASE, 
00166                      (time_t)(-1), NULL, dbh, op, rs,
00167                      slap_anlist_all_attributes,
00168                      BACKSQL_ISF_GET_ENTRY );
00169 
00170        Debug( LDAP_DEBUG_TRACE,
00171               "   backsql_modrdn(): old parent entry id is " BACKSQL_IDFMT "\n",
00172               BACKSQL_IDARG(bsi.bsi_base_id.eid_id), 0, 0 );
00173 
00174        if ( rs->sr_err != LDAP_SUCCESS ) {
00175               Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
00176                      "could not retrieve renameDN ID - no such entry\n", 
00177                      0, 0, 0 );
00178               e = &p;
00179               goto done;
00180        }
00181 
00182        if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL,
00183                      newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) )
00184        {
00185               Debug( LDAP_DEBUG_TRACE, "   no access to parent\n", 0, 0, 0 );
00186               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
00187               goto done;
00188        }
00189 
00190        if ( newSuperior ) {
00191               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
00192               
00193               /*
00194                * namingContext "" is not supported
00195                */
00196               if ( BER_BVISEMPTY( newSuperior ) ) {
00197                      Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00198                             "newSuperior is \"\" - aborting\n", 0, 0, 0 );
00199                      rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
00200                      rs->sr_text = "not allowed within namingContext";
00201                      e = NULL;
00202                      goto done;
00203               }
00204 
00205               new_pdn = newSuperior;
00206               new_npdn = op->oq_modrdn.rs_nnewSup;
00207 
00208               /*
00209                * Check for children access to new parent
00210                */
00211               bsi.bsi_e = &n;
00212               rs->sr_err = backsql_init_search( &bsi, new_npdn,
00213                             LDAP_SCOPE_BASE, 
00214                             (time_t)(-1), NULL, dbh, op, rs,
00215                             slap_anlist_all_attributes,
00216                             ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
00217               if ( rs->sr_err != LDAP_SUCCESS ) {
00218                      Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
00219                             "could not retrieve renameDN ID - no such entry\n", 
00220                             0, 0, 0 );
00221                      e = &n;
00222                      goto done;
00223               }
00224 
00225               n_id = bsi.bsi_base_id;
00226 
00227               Debug( LDAP_DEBUG_TRACE,
00228                      "   backsql_modrdn(): new parent entry id=" BACKSQL_IDFMT "\n",
00229                      BACKSQL_IDARG(n_id.eid_id), 0, 0 );
00230 
00231               if ( !access_allowed( op, &n, slap_schema.si_ad_children, 
00232                                    NULL, ACL_WADD, NULL ) ) {
00233                      Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00234                                    "no access to new parent \"%s\"\n", 
00235                                    new_pdn->bv_val, 0, 0 );
00236                      rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
00237                      e = &n;
00238                      goto done;
00239               }
00240 
00241        } else {
00242               n_id = bsi.bsi_base_id;
00243               new_pdn = &pdn;
00244               new_npdn = &pndn;
00245        }
00246 
00247        memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
00248 
00249        if ( newSuperior && dn_match( &pndn, new_npdn ) ) {
00250               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00251                      "newSuperior is equal to old parent - ignored\n",
00252                      0, 0, 0 );
00253               newSuperior = NULL;
00254        }
00255 
00256        if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
00257               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00258                      "newSuperior is equal to entry being moved "
00259                      "- aborting\n", 0, 0, 0 );
00260               rs->sr_err = LDAP_OTHER;
00261               rs->sr_text = "newSuperior is equal to old DN";
00262               e = &r;
00263               goto done;
00264        }
00265 
00266        build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn,
00267                      op->o_tmpmemctx );
00268        build_new_dn( &new_ndn, new_npdn, &op->oq_modrdn.rs_nnewrdn,
00269                      op->o_tmpmemctx );
00270        
00271        Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): new entry dn is \"%s\"\n",
00272                      new_dn.bv_val, 0, 0 );
00273 
00274        realnew_dn = new_dn;
00275        if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) {
00276               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(\"%s\"): "
00277                      "backsql_api_dn2odbc(\"%s\") failed\n", 
00278                      op->o_req_dn.bv_val, realnew_dn.bv_val, 0 );
00279               SQLFreeStmt( sth, SQL_DROP );
00280 
00281               rs->sr_text = "SQL-backend error";
00282               rs->sr_err = LDAP_OTHER;
00283               e = NULL;
00284               goto done;
00285        }
00286 
00287        Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00288               "executing renentry_stmt\n", 0, 0, 0 );
00289 
00290        rc = backsql_Prepare( dbh, &sth, bi->sql_renentry_stmt, 0 );
00291        if ( rc != SQL_SUCCESS ) {
00292               Debug( LDAP_DEBUG_TRACE,
00293                      "   backsql_modrdn(): "
00294                      "error preparing renentry_stmt\n", 0, 0, 0 );
00295               backsql_PrintErrors( bi->sql_db_env, dbh, 
00296                             sth, rc );
00297 
00298               rs->sr_text = "SQL-backend error";
00299               rs->sr_err = LDAP_OTHER;
00300               e = NULL;
00301               goto done;
00302        }
00303 
00304        rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn );
00305        if ( rc != SQL_SUCCESS ) {
00306               Debug( LDAP_DEBUG_TRACE,
00307                      "   backsql_modrdn(): "
00308                      "error binding DN parameter for objectClass %s\n",
00309                      oc->bom_oc->soc_cname.bv_val, 0, 0 );
00310               backsql_PrintErrors( bi->sql_db_env, dbh, 
00311                      sth, rc );
00312               SQLFreeStmt( sth, SQL_DROP );
00313 
00314               rs->sr_text = "SQL-backend error";
00315               rs->sr_err = LDAP_OTHER;
00316               e = NULL;
00317               goto done;
00318        }
00319 
00320        rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &n_id.eid_id );
00321        if ( rc != SQL_SUCCESS ) {
00322               Debug( LDAP_DEBUG_TRACE,
00323                      "   backsql_modrdn(): "
00324                      "error binding parent ID parameter for objectClass %s\n",
00325                      oc->bom_oc->soc_cname.bv_val, 0, 0 );
00326               backsql_PrintErrors( bi->sql_db_env, dbh, 
00327                      sth, rc );
00328               SQLFreeStmt( sth, SQL_DROP );
00329 
00330               rs->sr_text = "SQL-backend error";
00331               rs->sr_err = LDAP_OTHER;
00332               e = NULL;
00333               goto done;
00334        }
00335 
00336        rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &e_id.eid_keyval );
00337        if ( rc != SQL_SUCCESS ) {
00338               Debug( LDAP_DEBUG_TRACE,
00339                      "   backsql_modrdn(): "
00340                      "error binding entry ID parameter for objectClass %s\n",
00341                      oc->bom_oc->soc_cname.bv_val, 0, 0 );
00342               backsql_PrintErrors( bi->sql_db_env, dbh, 
00343                      sth, rc );
00344               SQLFreeStmt( sth, SQL_DROP );
00345 
00346               rs->sr_text = "SQL-backend error";
00347               rs->sr_err = LDAP_OTHER;
00348               e = NULL;
00349               goto done;
00350        }
00351 
00352        rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_id );
00353        if ( rc != SQL_SUCCESS ) {
00354               Debug( LDAP_DEBUG_TRACE,
00355                      "   backsql_modrdn(): "
00356                      "error binding ID parameter for objectClass %s\n",
00357                      oc->bom_oc->soc_cname.bv_val, 0, 0 );
00358               backsql_PrintErrors( bi->sql_db_env, dbh, 
00359                      sth, rc );
00360               SQLFreeStmt( sth, SQL_DROP );
00361 
00362               rs->sr_text = "SQL-backend error";
00363               rs->sr_err = LDAP_OTHER;
00364               e = NULL;
00365               goto done;
00366        }
00367 
00368        rc = SQLExecute( sth );
00369        if ( rc != SQL_SUCCESS ) {
00370               Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(): "
00371                      "could not rename ldap_entries record\n", 0, 0, 0 );
00372               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00373               SQLFreeStmt( sth, SQL_DROP );
00374               rs->sr_err = LDAP_OTHER;
00375               rs->sr_text = "SQL-backend error";
00376               e = NULL;
00377               goto done;
00378        }
00379        SQLFreeStmt( sth, SQL_DROP );
00380 
00381        assert( op->orr_modlist != NULL );
00382 
00383        slap_mods_opattrs( op, &op->orr_modlist, 1 );
00384 
00385        assert( e_id.eid_oc != NULL );
00386        oc = e_id.eid_oc;
00387        rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist );
00388        slap_graduate_commit_csn( op );
00389        if ( rs->sr_err != LDAP_SUCCESS ) {
00390               e = &r;
00391               goto done;
00392        }
00393 
00394        if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
00395               char          textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
00396 
00397               backsql_entry_clean( op, &r );
00398               (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
00399 
00400               bsi.bsi_e = &r;
00401               rs->sr_err = backsql_init_search( &bsi, &new_ndn,
00402                             LDAP_SCOPE_BASE, 
00403                             (time_t)(-1), NULL, dbh, op, rs,
00404                             slap_anlist_all_attributes,
00405                             ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
00406               switch ( rs->sr_err ) {
00407               case LDAP_SUCCESS:
00408                      break;
00409 
00410               case LDAP_REFERRAL:
00411                      if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
00412                                    dn_match( &new_ndn, &bsi.bsi_e->e_nname ) )
00413                      {
00414                             rs->sr_err = LDAP_SUCCESS;
00415                             rs->sr_text = NULL;
00416                             rs->sr_matched = NULL;
00417                             if ( rs->sr_ref ) {
00418                                    ber_bvarray_free( rs->sr_ref );
00419                                    rs->sr_ref = NULL;
00420                             }
00421                             break;
00422                      }
00423                      e = &r;
00424                      /* fallthru */
00425 
00426               default:
00427                      Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
00428                             "could not retrieve modrdnDN ID - no such entry\n", 
00429                             0, 0, 0 );
00430                      if ( !BER_BVISNULL( &r.e_nname ) ) {
00431                             /* FIXME: should always be true! */
00432                             e = &r;
00433 
00434                      } else {
00435                             e = NULL;
00436                      }
00437                      goto done;
00438               }
00439 
00440               e_id = bsi.bsi_base_id;
00441 
00442               rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0, NULL,
00443                      &rs->sr_text, textbuf, sizeof( textbuf ) );
00444               if ( rs->sr_err != LDAP_SUCCESS ) {
00445                      Debug( LDAP_DEBUG_TRACE, "   backsql_modrdn(\"%s\"): "
00446                             "entry failed schema check -- aborting\n",
00447                             r.e_name.bv_val, 0, 0 );
00448                      e = NULL;
00449                      goto done;
00450               }
00451        }
00452 
00453 done:;
00454        if ( e != NULL ) {
00455               if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
00456                                    ACL_DISCLOSE, NULL ) )
00457               {
00458                      rs->sr_err = LDAP_NO_SUCH_OBJECT;
00459                      rs->sr_text = NULL;
00460                      rs->sr_matched = NULL;
00461                      if ( rs->sr_ref ) {
00462                             ber_bvarray_free( rs->sr_ref );
00463                             rs->sr_ref = NULL;
00464                      }
00465               }
00466        }
00467 
00468        /*
00469         * Commit only if all operations succeed
00470         */
00471        if ( sth != SQL_NULL_HSTMT ) {
00472               SQLUSMALLINT  CompletionType = SQL_ROLLBACK;
00473        
00474               if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
00475                      CompletionType = SQL_COMMIT;
00476               }
00477 
00478               SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
00479        }
00480 
00481        if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
00482               rs->sr_err = LDAP_X_NO_OPERATION;
00483        }
00484 
00485        send_ldap_result( op, rs );
00486        slap_graduate_commit_csn( op );
00487 
00488        if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) {
00489               ch_free( realnew_dn.bv_val );
00490        }
00491 
00492        if ( !BER_BVISNULL( &new_dn ) ) {
00493               slap_sl_free( new_dn.bv_val, op->o_tmpmemctx );
00494        }
00495        
00496        if ( !BER_BVISNULL( &new_ndn ) ) {
00497               slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx );
00498        }
00499        
00500        if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
00501               (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
00502        }
00503 
00504        if ( !BER_BVISNULL( &n_id.eid_ndn ) ) {
00505               (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx );
00506        }
00507 
00508        if ( !BER_BVISNULL( &r.e_nname ) ) {
00509               backsql_entry_clean( op, &r );
00510        }
00511 
00512        if ( !BER_BVISNULL( &p.e_nname ) ) {
00513               backsql_entry_clean( op, &p );
00514        }
00515 
00516        if ( !BER_BVISNULL( &n.e_nname ) ) {
00517               backsql_entry_clean( op, &n );
00518        }
00519 
00520        if ( rs->sr_ref ) {
00521               ber_bvarray_free( rs->sr_ref );
00522               rs->sr_ref = NULL;
00523        }
00524 
00525        Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
00526 
00527        return rs->sr_err;
00528 }
00529