Back to index

openldap  2.4.31
delete.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 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00016  * All rights reserved.
00017  *
00018  * Redistribution and use in source and binary forms are permitted
00019  * provided that this notice is preserved and that due credit is given
00020  * to the University of Michigan at Ann Arbor. The name of the University
00021  * may not be used to endorse or promote products derived from this
00022  * software without specific prior written permission. This software
00023  * is provided ``as is'' without express or implied warranty.
00024  */
00025 
00026 #include "portable.h"
00027 
00028 #include <stdio.h>
00029 
00030 #include <ac/string.h>
00031 #include <ac/socket.h>
00032 
00033 #include "slap.h"
00034 
00035 #include "lutil.h"
00036 
00037 int
00038 do_delete(
00039     Operation *op,
00040     SlapReply *rs )
00041 {
00042        struct berval dn = BER_BVNULL;
00043 
00044        Debug( LDAP_DEBUG_TRACE, "%s do_delete\n",
00045               op->o_log_prefix, 0, 0 );
00046        /*
00047         * Parse the delete request.  It looks like this:
00048         *
00049         *     DelRequest := DistinguishedName
00050         */
00051 
00052        if ( ber_scanf( op->o_ber, "m", &dn ) == LBER_ERROR ) {
00053               Debug( LDAP_DEBUG_ANY, "%s do_delete: ber_scanf failed\n",
00054                      op->o_log_prefix, 0, 0 );
00055               send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
00056               return SLAPD_DISCONNECT;
00057        }
00058 
00059        if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
00060               Debug( LDAP_DEBUG_ANY, "%s do_delete: get_ctrls failed\n",
00061                      op->o_log_prefix, 0, 0 );
00062               goto cleanup;
00063        } 
00064 
00065        rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn,
00066               op->o_tmpmemctx );
00067        if( rs->sr_err != LDAP_SUCCESS ) {
00068               Debug( LDAP_DEBUG_ANY, "%s do_delete: invalid dn (%s)\n",
00069                      op->o_log_prefix, dn.bv_val, 0 );
00070               send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
00071               goto cleanup;
00072        }
00073 
00074        Statslog( LDAP_DEBUG_STATS, "%s DEL dn=\"%s\"\n",
00075               op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 );
00076 
00077        if( op->o_req_ndn.bv_len == 0 ) {
00078               Debug( LDAP_DEBUG_ANY, "%s do_delete: root dse!\n",
00079                      op->o_log_prefix, 0, 0 );
00080               /* protocolError would likely be a more appropriate error */
00081               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
00082                      "cannot delete the root DSE" );
00083               goto cleanup;
00084 
00085        } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
00086               Debug( LDAP_DEBUG_ANY, "%s do_delete: subschema subentry!\n",
00087                      op->o_log_prefix, 0, 0 );
00088               /* protocolError would likely be a more appropriate error */
00089               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
00090                      "cannot delete the root DSE" );
00091               goto cleanup;
00092        }
00093 
00094        op->o_bd = frontendDB;
00095        rs->sr_err = frontendDB->be_delete( op, rs );
00096 
00097 #ifdef LDAP_X_TXN
00098        if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) {
00099               /* skip cleanup */
00100               return rs->sr_err;
00101        }
00102 #endif
00103 
00104 cleanup:;
00105        op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
00106        op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
00107        return rs->sr_err;
00108 }
00109 
00110 int
00111 fe_op_delete( Operation *op, SlapReply *rs )
00112 {
00113        struct berval pdn = BER_BVNULL;
00114        BackendDB     *op_be, *bd = op->o_bd;
00115        
00116        /*
00117         * We could be serving multiple database backends.  Select the
00118         * appropriate one, or send a referral to our "referral server"
00119         * if we don't hold it.
00120         */
00121        op->o_bd = select_backend( &op->o_req_ndn, 1 );
00122        if ( op->o_bd == NULL ) {
00123               op->o_bd = bd;
00124               rs->sr_ref = referral_rewrite( default_referral,
00125                      NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
00126 
00127               if (!rs->sr_ref) rs->sr_ref = default_referral;
00128               if ( rs->sr_ref != NULL ) {
00129                      rs->sr_err = LDAP_REFERRAL;
00130                      send_ldap_result( op, rs );
00131 
00132                      if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
00133               } else {
00134                      send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
00135                             "no global superior knowledge" );
00136               }
00137               goto cleanup;
00138        }
00139 
00140        /* If we've got a glued backend, check the real backend */
00141        op_be = op->o_bd;
00142        if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
00143               op->o_bd = select_backend( &op->o_req_ndn, 0 );
00144        }
00145 
00146        /* check restrictions */
00147        if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
00148               send_ldap_result( op, rs );
00149               goto cleanup;
00150        }
00151 
00152        /* check for referrals */
00153        if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
00154               goto cleanup;
00155        }
00156 
00157        /*
00158         * do the delete if 1 && (2 || 3)
00159         * 1) there is a delete function implemented in this backend;
00160         * 2) this backend is master for what it holds;
00161         * 3) it's a replica and the dn supplied is the update_ndn.
00162         */
00163        if ( op->o_bd->be_delete ) {
00164               /* do the update here */
00165               int repl_user = be_isupdate( op );
00166               if ( !SLAP_SINGLE_SHADOW(op->o_bd) || repl_user ) {
00167                      struct berval org_req_dn = BER_BVNULL;
00168                      struct berval org_req_ndn = BER_BVNULL;
00169                      struct berval org_dn = BER_BVNULL;
00170                      struct berval org_ndn = BER_BVNULL;
00171                      int           org_managedsait;
00172 
00173                      op->o_bd = op_be;
00174                      op->o_bd->be_delete( op, rs );
00175 
00176                      org_req_dn = op->o_req_dn;
00177                      org_req_ndn = op->o_req_ndn;
00178                      org_dn = op->o_dn;
00179                      org_ndn = op->o_ndn;
00180                      org_managedsait = get_manageDSAit( op );
00181                      op->o_dn = op->o_bd->be_rootdn;
00182                      op->o_ndn = op->o_bd->be_rootndn;
00183                      op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
00184 
00185                      while ( rs->sr_err == LDAP_SUCCESS &&
00186                             op->o_delete_glue_parent )
00187                      {
00188                             op->o_delete_glue_parent = 0;
00189                             if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
00190                                    slap_callback cb = { NULL, NULL, NULL, NULL };
00191                                    cb.sc_response = slap_null_cb;
00192                                    dnParent( &op->o_req_ndn, &pdn );
00193                                    op->o_req_dn = pdn;
00194                                    op->o_req_ndn = pdn;
00195                                    op->o_callback = &cb;
00196                                    op->o_bd->be_delete( op, rs );
00197                             } else {
00198                                    break;
00199                             }
00200                      }
00201 
00202                      op->o_managedsait = org_managedsait;
00203                      op->o_dn = org_dn;
00204                      op->o_ndn = org_ndn;
00205                      op->o_req_dn = org_req_dn;
00206                      op->o_req_ndn = org_req_ndn;
00207                      op->o_delete_glue_parent = 0;
00208 
00209               } else {
00210                      BerVarray defref = op->o_bd->be_update_refs
00211                             ? op->o_bd->be_update_refs : default_referral;
00212 
00213                      if ( defref != NULL ) {
00214                             rs->sr_ref = referral_rewrite( defref,
00215                                    NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
00216                             if (!rs->sr_ref) rs->sr_ref = defref;
00217                             rs->sr_err = LDAP_REFERRAL;
00218                             send_ldap_result( op, rs );
00219 
00220                             if (rs->sr_ref != defref) ber_bvarray_free( rs->sr_ref );
00221 
00222                      } else {
00223                             send_ldap_error( op, rs,
00224                                    LDAP_UNWILLING_TO_PERFORM,
00225                                    "shadow context; no update referral" );
00226                      }
00227               }
00228 
00229        } else {
00230               send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
00231                      "operation not supported within namingContext" );
00232        }
00233 
00234 cleanup:;
00235        op->o_bd = bd;
00236        return rs->sr_err;
00237 }