~ubuntu-branches/ubuntu/wily/389-ds-base/wily

« back to all changes in this revision

Viewing changes to ldap/servers/slapd/delete.c

  • Committer: Package Import Robot
  • Author(s): Krzysztof Klimonda
  • Date: 2012-03-27 14:26:16 UTC
  • Revision ID: package-import@ubuntu.com-20120327142616-xt24t6nffm3f7ybz
Tags: upstream-1.2.11.7
ImportĀ upstreamĀ versionĀ 1.2.11.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** BEGIN COPYRIGHT BLOCK
 
2
 * This Program is free software; you can redistribute it and/or modify it under
 
3
 * the terms of the GNU General Public License as published by the Free Software
 
4
 * Foundation; version 2 of the License.
 
5
 * 
 
6
 * This Program is distributed in the hope that it will be useful, but WITHOUT
 
7
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
8
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
9
 * 
 
10
 * You should have received a copy of the GNU General Public License along with
 
11
 * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
12
 * Place, Suite 330, Boston, MA 02111-1307 USA.
 
13
 * 
 
14
 * In addition, as a special exception, Red Hat, Inc. gives You the additional
 
15
 * right to link the code of this Program with code not covered under the GNU
 
16
 * General Public License ("Non-GPL Code") and to distribute linked combinations
 
17
 * including the two, subject to the limitations in this paragraph. Non-GPL Code
 
18
 * permitted under this exception must only link to the code of this Program
 
19
 * through those well defined interfaces identified in the file named EXCEPTION
 
20
 * found in the source code files (the "Approved Interfaces"). The files of
 
21
 * Non-GPL Code may instantiate templates or use macros or inline functions from
 
22
 * the Approved Interfaces without causing the resulting work to be covered by
 
23
 * the GNU General Public License. Only Red Hat, Inc. may make changes or
 
24
 * additions to the list of Approved Interfaces. You must obey the GNU General
 
25
 * Public License in all respects for all of the Program code and other code used
 
26
 * in conjunction with the Program except the Non-GPL Code covered by this
 
27
 * exception. If you modify this file, you may extend this exception to your
 
28
 * version of the file, but you are not obligated to do so. If you do not wish to
 
29
 * provide this exception without modification, you must delete this exception
 
30
 * statement from your version and license this file solely under the GPL without
 
31
 * exception. 
 
32
 * 
 
33
 * 
 
34
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
 
35
 * Copyright (C) 2005 Red Hat, Inc.
 
36
 * All rights reserved.
 
37
 * END COPYRIGHT BLOCK **/
 
38
 
 
39
#ifdef HAVE_CONFIG_H
 
40
#  include <config.h>
 
41
#endif
 
42
 
 
43
/*
 
44
 * Copyright (c) 1995 Regents of the University of Michigan.
 
45
 * All rights reserved.
 
46
 *
 
47
 * Redistribution and use in source and binary forms are permitted
 
48
 * provided that this notice is preserved and that due credit is given
 
49
 * to the University of Michigan at Ann Arbor. The name of the University
 
50
 * may not be used to endorse or promote products derived from this
 
51
 * software without specific prior written permission. This software
 
52
 * is provided ``as is'' without express or implied warranty.
 
53
 */
 
54
 
 
55
#include <stdio.h>
 
56
#include <string.h>
 
57
#include <sys/types.h>
 
58
#ifndef _WIN32
 
59
#include <sys/socket.h>
 
60
#endif
 
61
#include "slap.h"
 
62
#include "pratom.h"
 
63
 
 
64
/* Forward declarations */
 
65
static int delete_internal_pb (Slapi_PBlock *pb); 
 
66
static void op_shared_delete (Slapi_PBlock *pb);
 
67
 
 
68
/* This function is called to process operation that come over external connections */
 
69
void
 
70
do_delete( Slapi_PBlock *pb )
 
71
{
 
72
        Slapi_Operation *operation;
 
73
        BerElement      *ber;
 
74
        char        *rawdn = NULL;
 
75
        int                     err = 0;
 
76
 
 
77
        LDAPDebug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
 
78
        
 
79
        slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
 
80
        ber = operation->o_ber;
 
81
 
 
82
        /* count the delete request */
 
83
        slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
 
84
 
 
85
        /*
 
86
         * Parse the delete request.  It looks like this:
 
87
         *
 
88
         *      DelRequest := DistinguishedName
 
89
         */
 
90
 
 
91
        if ( ber_scanf( pb->pb_op->o_ber, "a", &rawdn ) == LBER_ERROR ) {
 
92
                LDAPDebug( LDAP_DEBUG_ANY,
 
93
                    "ber_scanf failed (op=Delete; params=DN)\n", 0, 0, 0 );
 
94
                op_shared_log_error_access (pb, "DEL", "???", "decoding error");
 
95
                send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
 
96
                    NULL );
 
97
                goto free_and_return;
 
98
        }
 
99
        /* Check if we should be performing strict validation. */
 
100
        if (config_get_dn_validate_strict()) {
 
101
                /* check that the dn is formatted correctly */
 
102
                err = slapi_dn_syntax_check(pb, rawdn, 1);
 
103
                if (err) { /* syntax check failed */
 
104
                        op_shared_log_error_access(pb, "DEL", rawdn?rawdn:"",
 
105
                                                        "strict: invalid dn");
 
106
                        send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
 
107
                                                         NULL, "invalid dn", 0, NULL);
 
108
                        goto free_and_return;
 
109
                }
 
110
        }
 
111
 
 
112
        /*
 
113
         * in LDAPv3 there can be optional control extensions on
 
114
         * the end of an LDAPMessage. we need to read them in and
 
115
         * pass them to the backend.
 
116
         */
 
117
        if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) {
 
118
                op_shared_log_error_access (pb, "DEL", rawdn, "decoding error");
 
119
                send_ldap_result( pb, err, NULL, NULL, 0, NULL );
 
120
                goto free_and_return;
 
121
        }
 
122
 
 
123
        LDAPDebug1Arg( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", rawdn );
 
124
 
 
125
        slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot );
 
126
        slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, rawdn);
 
127
 
 
128
        op_shared_delete (pb);
 
129
 
 
130
free_and_return:;
 
131
        slapi_ch_free ((void**)&rawdn);
 
132
}
 
133
 
 
134
/* This function is used to issue internal delete operation
 
135
   This is an old style API. Its use is discoraged because it is not extendable and
 
136
   because it does not allow to check whether plugin has right to access part of the
 
137
   tree it is trying to modify. Use slapi_delete_internal_pb instead */
 
138
Slapi_PBlock *
 
139
slapi_delete_internal(const char *idn, LDAPControl **controls, int dummy)
 
140
{
 
141
    Slapi_PBlock        pb;
 
142
    Slapi_PBlock    *result_pb;
 
143
    int             opresult;
 
144
 
 
145
    pblock_init (&pb);
 
146
 
 
147
    slapi_delete_internal_set_pb (&pb, idn, controls, NULL, plugin_get_default_component_id(), 0);
 
148
 
 
149
        delete_internal_pb (&pb);
 
150
        
 
151
        result_pb = slapi_pblock_new();
 
152
        if (result_pb)
 
153
        {
 
154
                slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);    
 
155
                slapi_pblock_set(result_pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
 
156
        }
 
157
        pblock_done(&pb);
 
158
    
 
159
    return result_pb;
 
160
}
 
161
 
 
162
/*      This is new style API to issue internal delete operation.
 
163
        pblock should contain the following data (can be set via call to slapi_delete_internal_set_pb):
 
164
        For uniqueid based operation:
 
165
                SLAPI_TARGET_DN set to dn that allows to select right backend, can be stale
 
166
                SLAPI_TARGET_UNIQUEID set to the uniqueid of the entry we are looking for
 
167
                SLAPI_CONTROLS_ARG set to request controls if present
 
168
 
 
169
        For dn based search:
 
170
                SLAPI_TARGET_DN set to the entry dn
 
171
                SLAPI_CONTROLS_ARG set to request controls if present                                           
 
172
 */
 
173
int slapi_delete_internal_pb (Slapi_PBlock *pb)
 
174
{
 
175
        if (pb == NULL)
 
176
                return -1;
 
177
 
 
178
        if (!allow_operation (pb))
 
179
        {
 
180
                slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
 
181
                                                 "This plugin is not configured to access operation target data", 0, NULL );
 
182
                return 0;
 
183
        }
 
184
 
 
185
        return delete_internal_pb (pb);
 
186
}
 
187
 
 
188
/* Initialize a pblock for a call to slapi_delete_internal_pb() */
 
189
void
 
190
slapi_delete_internal_set_pb (Slapi_PBlock *pb,
 
191
                              const char *rawdn,
 
192
                              LDAPControl **controls, const char *uniqueid, 
 
193
                              Slapi_ComponentId *plugin_identity, 
 
194
                              int operation_flags)
 
195
{  
 
196
        Operation *op;
 
197
        PR_ASSERT (pb != NULL);
 
198
        if (pb == NULL || rawdn == NULL)
 
199
        {
 
200
                slapi_log_error(SLAPI_LOG_FATAL, NULL, 
 
201
                                                "slapi_delete_internal_set_pb: NULL parameter\n");
 
202
                return;
 
203
        }
 
204
 
 
205
        op = internal_operation_new(SLAPI_OPERATION_DELETE,operation_flags);
 
206
        slapi_pblock_set(pb, SLAPI_OPERATION, op);
 
207
        slapi_pblock_set(pb, SLAPI_ORIGINAL_TARGET, (void*)rawdn);
 
208
        slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
 
209
        if (uniqueid)
 
210
        {
 
211
                slapi_pblock_set(pb, SLAPI_TARGET_UNIQUEID, (void*)uniqueid);
 
212
        }
 
213
        slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, plugin_identity);
 
214
}
 
215
 
 
216
/* Helper functions */
 
217
 
 
218
static int delete_internal_pb (Slapi_PBlock *pb)
 
219
{
 
220
        LDAPControl             **controls;
 
221
        Operation       *op;
 
222
    int             opresult = 0;
 
223
 
 
224
        PR_ASSERT (pb != NULL);
 
225
 
 
226
        slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
 
227
 
 
228
        slapi_pblock_get(pb, SLAPI_OPERATION, &op);
 
229
    op->o_handler_data   = &opresult;
 
230
    op->o_result_handler = internal_getresult_callback;
 
231
 
 
232
        slapi_pblock_set(pb, SLAPI_OPERATION, op);
 
233
        slapi_pblock_set(pb, SLAPI_REQCONTROLS, controls);
 
234
 
 
235
        /* set parameters common for all internal operations */
 
236
        set_common_params (pb);
 
237
 
 
238
        /* set actions taken to process the operation */
 
239
        set_config_params (pb);
 
240
 
 
241
        /* perform delete operation */
 
242
        op_shared_delete (pb);
 
243
 
 
244
        slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
 
245
 
 
246
        return 0;
 
247
}
 
248
 
 
249
static void op_shared_delete (Slapi_PBlock *pb)
 
250
{
 
251
        char                    *rawdn = NULL;
 
252
        const char              *dn = NULL;
 
253
        Slapi_Backend   *be = NULL;
 
254
        int                             internal_op;
 
255
        Slapi_DN                *sdn = NULL;
 
256
        Slapi_Operation *operation;
 
257
        Slapi_Entry *referral;
 
258
        Slapi_Entry     *ecopy = NULL;
 
259
        char errorbuf[BUFSIZ];
 
260
        int                             err;
 
261
        char            *proxydn = NULL;
 
262
        char            *proxystr = NULL;
 
263
        int             proxy_err = LDAP_SUCCESS;
 
264
        char            *errtext = NULL;
 
265
 
 
266
        slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &rawdn);
 
267
        slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
 
268
        internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);
 
269
 
 
270
        sdn = slapi_sdn_new_dn_byval(rawdn);
 
271
        dn = slapi_sdn_get_dn(sdn);
 
272
        slapi_pblock_set(pb, SLAPI_DELETE_TARGET_SDN, (void*)sdn);
 
273
        if (rawdn && (strlen(rawdn) > 0) && (NULL == dn)) {
 
274
                /* normalization failed */
 
275
                op_shared_log_error_access(pb, "DEL", rawdn, "invalid dn");
 
276
                send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
 
277
                                 NULL, "invalid dn", 0, NULL);
 
278
                goto free_and_return;
 
279
        }
 
280
 
 
281
        /* target spec is used to decide which plugins are applicable for the operation */
 
282
        operation_set_target_spec (operation, sdn);
 
283
 
 
284
        /* get the proxy auth dn if the proxy auth control is present */
 
285
        proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext);
 
286
 
 
287
        if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
 
288
        {
 
289
                if (proxydn)
 
290
                {
 
291
                        proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
 
292
                }
 
293
 
 
294
                if (!internal_op )
 
295
                {
 
296
                        slapi_log_access(LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d DEL dn=\"%s\"%s\n",
 
297
                                                        pb->pb_conn->c_connid, 
 
298
                                                        pb->pb_op->o_opid,
 
299
                                                        slapi_sdn_get_dn(sdn),
 
300
                                                        proxystr ? proxystr: "");
 
301
                }
 
302
                else
 
303
                {
 
304
                        slapi_log_access(LDAP_DEBUG_ARGS, "conn=%s op=%d DEL dn=\"%s\"%s\n",
 
305
                                                        LOG_INTERNAL_OP_CON_ID,
 
306
                                                        LOG_INTERNAL_OP_OP_ID,
 
307
                                                        slapi_sdn_get_dn(sdn),
 
308
                                                        proxystr ? proxystr: "");
 
309
                }
 
310
        }
 
311
 
 
312
        /* If we encountered an error parsing the proxy control, return an error
 
313
         * to the client.  We do this here to ensure that we log the operation first. */
 
314
        if (proxy_err != LDAP_SUCCESS)
 
315
        {
 
316
                send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL);
 
317
                goto free_and_return;
 
318
        }
 
319
 
 
320
        /*
 
321
         * We could be serving multiple database backends.  Select the
 
322
         * appropriate one.
 
323
         */
 
324
        if ((err = slapi_mapping_tree_select(pb, &be, &referral, errorbuf)) != LDAP_SUCCESS) {
 
325
                send_ldap_result(pb, err, NULL, errorbuf, 0, NULL);
 
326
                be = NULL;
 
327
                goto free_and_return;
 
328
        }
 
329
 
 
330
        if (referral)
 
331
        {
 
332
                int managedsait;
 
333
 
 
334
                slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
 
335
                if (managedsait)
 
336
                {
 
337
                        send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
 
338
                                        "cannot delete referral", 0, NULL);
 
339
                        slapi_entry_free(referral);
 
340
                        goto free_and_return;
 
341
                }
 
342
        
 
343
                send_referrals_from_entry(pb,referral);
 
344
                slapi_entry_free(referral);
 
345
                goto free_and_return;
 
346
        }
 
347
 
 
348
        slapi_pblock_set(pb, SLAPI_BACKEND, be);                        
 
349
 
 
350
        /*
 
351
         * call the pre-delete plugins. if they succeed, call
 
352
         * the backend delete function. then call the
 
353
         * post-delete plugins.
 
354
         */
 
355
        if (plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN : 
 
356
                                                        SLAPI_PLUGIN_PRE_DELETE_FN) == 0)
 
357
        {
 
358
                int     rc;
 
359
 
 
360
                slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
 
361
                set_db_default_result_handlers(pb);
 
362
                if (be->be_delete != NULL)
 
363
                {
 
364
                        if ((rc = (*be->be_delete)(pb)) == 0)
 
365
                        {
 
366
                                /* we don't perform acl check for internal operations */
 
367
                                /* Dont update aci store for remote acis              */
 
368
                                if ((!internal_op) && 
 
369
                                        (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
 
370
                                        plugin_call_acl_mods_update (pb, SLAPI_OPERATION_DELETE);
 
371
 
 
372
                                if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_AUDIT))
 
373
                                        write_audit_log_entry(pb); /* Record the operation in the audit log */
 
374
 
 
375
                                slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &ecopy);
 
376
                                do_ps_service(ecopy, NULL, LDAP_CHANGETYPE_DELETE, 0);
 
377
                        }
 
378
                        else
 
379
                        {
 
380
                                if (rc == SLAPI_FAIL_DISKFULL)
 
381
                                {
 
382
                                        operation_out_of_disk_space();
 
383
                                        goto free_and_return;
 
384
                                }
 
385
                        }
 
386
                }
 
387
 
 
388
                slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc);
 
389
                plugin_call_plugins(pb, internal_op ? SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN :
 
390
                                                        SLAPI_PLUGIN_POST_DELETE_FN);
 
391
        }
 
392
 
 
393
free_and_return:
 
394
        if (be) {
 
395
                slapi_be_Unlock(be);
 
396
        }
 
397
        {
 
398
                char *coldn = NULL;
 
399
                Slapi_Entry *epre = NULL, *eparent = NULL;
 
400
                slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &epre);
 
401
                slapi_pblock_get(pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, &eparent);
 
402
                slapi_pblock_set(pb, SLAPI_ENTRY_PRE_OP, NULL);
 
403
                slapi_pblock_set(pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, NULL);
 
404
                if (epre == eparent) {
 
405
                        eparent = NULL;
 
406
                }
 
407
                slapi_entry_free(epre);
 
408
                slapi_entry_free(eparent);
 
409
                slapi_pblock_get(pb, SLAPI_URP_NAMING_COLLISION_DN, &coldn);
 
410
                slapi_ch_free_string(&coldn);
 
411
        }
 
412
 
 
413
        slapi_pblock_get(pb, SLAPI_DELETE_TARGET_SDN, &sdn);
 
414
        slapi_sdn_free(&sdn);
 
415
        slapi_ch_free_string(&proxydn);
 
416
        slapi_ch_free_string(&proxystr);
 
417
}