~ubuntu-branches/ubuntu/maverick/openldap/maverick-proposed

« back to all changes in this revision

Viewing changes to servers/slapd/back-ndb/delete.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug, Steve Langasek, Mathias Gug
  • Date: 2009-02-18 18:44:00 UTC
  • mfrom: (1.1.2 upstream) (0.1.2 lenny)
  • Revision ID: james.westby@ubuntu.com-20090218184400-zw4mjse9eywt5566
Tags: 2.4.14-0ubuntu1
[ Steve Langasek ]
* New upstream version
  - Fixes a bug with the pcache overlay not returning cached entries
    (closes: #497697)
  - Update evolution-ntlm patch to apply to current Makefiles.
  - (tentatively) drop gnutls-ciphers, since this bug was reported to be
    fixed upstream in 2.4.8.  The fix applied in 2.4.8 didn't match the
    patch from the bug report, so this should be watched for regressions.
* Build against db4.7 instead of db4.2 at last!  Closes: #421946.
* Build with --disable-ndb, to avoid a misbuild when libmysqlclient is
  installed in the build environment.
* New patch, no-crlcheck-for-gnutls, to fix a build failure when using
  --with-tls=gnutls.

[ Mathias Gug ]
* Merge from debian unstable, remaining changes:
  - debian/apparmor-profile: add AppArmor profile
  - debian/slapd.postinst: Reload AA profile on configuration
  - updated debian/slapd.README.Debian for note on AppArmor
  - debian/control: Recommends apparmor >= 2.1+1075-0ubuntu6
  - debian/control: Conflicts with apparmor-profiles << 2.1+1075-0ubuntu4
    to make sure that if earlier version of apparmour-profiles gets
    installed it won't overwrite our profile.
  - Modify Maintainer value to match the DebianMaintainerField
    speficication.
  - follow ApparmorProfileMigration and force apparmor compalin mode on 
    some upgrades (LP: #203529)
  - debian/slapd.dirs: add etc/apparmor.d/force-complain
  - debian/slapd.preinst: create symlink for force-complain on pre-feisty
    upgrades, upgrades where apparmor-profiles profile is unchanged (ie
    non-enforcing) and upgrades where apparmor profile does not exist.
  - debian/slapd.postrm: remove symlink in force-complain/ on purge
  - debian/patches/fix-ucred-libc due to changes how newer glibc handle
    the ucred struct now.
  - debian/control:
    - Build-depend on libltdl7-dev rather then libltdl3-dev.
  - debian/patches/autogen.sh:
    - Call libtoolize with the --install option to install config.{guess,sub}
      files.
  - Don't use local statement in config script as it fails if /bin/sh
    points to bash (LP: #286063).
  - Disable the testsuite on hppa. Allows building of packages on this
    architecture again, once this package is in the archive.
    LP: #288908.
  - debian/slapd.postinst, debian/slapd.script-common: set correct ownership
    and permissions on /var/lib/ldap, /etc/ldap/slapd.d (group readable) and
    /var/run/slapd (world readable). (LP: #257667).
  - debian/patches/nssov-build, debian/rules: 
    Build and package the nss overlay.
    debian/schema/misc.ldif: add ldif file for the misc schema, which defines
    rfc822MailMember (required by the nss overlay).
  - debian/{control,rules}: enable PIE hardening
  - Use cn=config as the default configuration backend instead of 
    slapd.conf. Migrate slapd.conf  file to /etc/ldap/slapd.d/ on upgrade
    asking the end user to enter a new password to control the access to the
    cn=config tree.
* debian/patches/corrupt-contextCSN: The contextCSN can get corrupted at
  times. (ITS: #5947)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* delete.cpp - ndb backend delete routine */
 
2
/* $OpenLDAP: pkg/ldap/servers/slapd/back-ndb/delete.cpp,v 1.3.2.2 2009/01/22 00:01:09 kurt Exp $ */
 
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
4
 *
 
5
 * Copyright 2008-2009 The OpenLDAP Foundation.
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted only as authorized by the OpenLDAP
 
10
 * Public License.
 
11
 *
 
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>.
 
15
 */
 
16
/* ACKNOWLEDGEMENTS:
 
17
 * This work was initially developed by Howard Chu for inclusion
 
18
 * in OpenLDAP Software. This work was sponsored by MySQL.
 
19
 */
 
20
 
 
21
#include "portable.h"
 
22
 
 
23
#include <stdio.h>
 
24
#include <ac/string.h>
 
25
 
 
26
#include "lutil.h"
 
27
#include "back-ndb.h"
 
28
 
 
29
static struct berval glue_bv = BER_BVC("glue");
 
30
 
 
31
int
 
32
ndb_back_delete( Operation *op, SlapReply *rs )
 
33
{
 
34
        struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
 
35
        Entry   e = {0};
 
36
        Entry   p = {0};
 
37
        int             manageDSAit = get_manageDSAit( op );
 
38
        AttributeDescription *children = slap_schema.si_ad_children;
 
39
        AttributeDescription *entry = slap_schema.si_ad_entry;
 
40
 
 
41
        NdbArgs NA;
 
42
        NdbRdns rdns;
 
43
        struct berval matched;
 
44
 
 
45
        int     num_retries = 0;
 
46
 
 
47
        int     rc;
 
48
 
 
49
        LDAPControl **preread_ctrl = NULL;
 
50
        LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
 
51
        int num_ctrls = 0;
 
52
 
 
53
        Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(ndb_back_delete) ": %s\n",
 
54
                op->o_req_dn.bv_val, 0, 0 );
 
55
 
 
56
        ctrls[num_ctrls] = 0;
 
57
 
 
58
        /* allocate CSN */
 
59
        if ( BER_BVISNULL( &op->o_csn ) ) {
 
60
                struct berval csn;
 
61
                char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
 
62
 
 
63
                csn.bv_val = csnbuf;
 
64
                csn.bv_len = sizeof(csnbuf);
 
65
                slap_get_csn( op, &csn, 1 );
 
66
        }
 
67
 
 
68
        if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
 
69
                dnParent( &op->o_req_dn, &p.e_name );
 
70
                dnParent( &op->o_req_ndn, &p.e_nname );
 
71
        }
 
72
 
 
73
        /* Get our NDB handle */
 
74
        rs->sr_err = ndb_thread_handle( op, &NA.ndb );
 
75
        rdns.nr_num = 0;
 
76
        NA.rdns = &rdns;
 
77
        NA.ocs = NULL;
 
78
        NA.e = &e;
 
79
        e.e_name = op->o_req_dn;
 
80
        e.e_nname = op->o_req_ndn;
 
81
 
 
82
        if( 0 ) {
 
83
retry:  /* transaction retry */
 
84
                NA.txn->close();
 
85
                NA.txn = NULL;
 
86
                Debug( LDAP_DEBUG_TRACE,
 
87
                        "==> " LDAP_XSTRING(ndb_back_delete) ": retrying...\n",
 
88
                        0, 0, 0 );
 
89
                if ( op->o_abandon ) {
 
90
                        rs->sr_err = SLAPD_ABANDON;
 
91
                        goto return_results;
 
92
                }
 
93
                if ( NA.ocs ) {
 
94
                        ber_bvarray_free( NA.ocs );
 
95
                        NA.ocs = NULL;
 
96
                }
 
97
                ndb_trans_backoff( ++num_retries );
 
98
        }
 
99
 
 
100
        /* begin transaction */
 
101
        NA.txn = NA.ndb->startTransaction();
 
102
        rs->sr_text = NULL;
 
103
        if( !NA.txn ) {
 
104
                Debug( LDAP_DEBUG_TRACE,
 
105
                        LDAP_XSTRING(ndb_back_delete) ": startTransaction failed: %s (%d)\n",
 
106
                        NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
 
107
                rs->sr_err = LDAP_OTHER;
 
108
                rs->sr_text = "internal error";
 
109
                goto return_results;
 
110
        }
 
111
 
 
112
        /* get entry */
 
113
        rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched );
 
114
        switch( rs->sr_err ) {
 
115
        case 0:
 
116
        case LDAP_NO_SUCH_OBJECT:
 
117
                break;
 
118
#if 0
 
119
        case DB_LOCK_DEADLOCK:
 
120
        case DB_LOCK_NOTGRANTED:
 
121
                goto retry;
 
122
#endif
 
123
        case LDAP_BUSY:
 
124
                rs->sr_text = "ldap server busy";
 
125
                goto return_results;
 
126
        default:
 
127
                rs->sr_err = LDAP_OTHER;
 
128
                rs->sr_text = "internal error";
 
129
                goto return_results;
 
130
        }
 
131
 
 
132
        if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ||
 
133
                ( !manageDSAit && bvmatch( NA.ocs, &glue_bv ))) {
 
134
                Debug( LDAP_DEBUG_ARGS,
 
135
                        "<=- " LDAP_XSTRING(ndb_back_delete) ": no such object %s\n",
 
136
                        op->o_req_dn.bv_val, 0, 0);
 
137
 
 
138
                if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
 
139
                        rs->sr_matched = matched.bv_val;
 
140
                        if ( NA.ocs )
 
141
                                ndb_check_referral( op, rs, &NA );
 
142
                } else {
 
143
                        rs->sr_matched = p.e_name.bv_val;
 
144
                        rs->sr_err = LDAP_NO_SUCH_OBJECT;
 
145
                }
 
146
                goto return_results;
 
147
        }
 
148
 
 
149
        /* check parent for "children" acl */
 
150
        rs->sr_err = access_allowed( op, &p,
 
151
                children, NULL, ACL_WDEL, NULL );
 
152
 
 
153
        if ( !rs->sr_err  ) {
 
154
                Debug( LDAP_DEBUG_TRACE,
 
155
                        "<=- " LDAP_XSTRING(ndb_back_delete) ": no write "
 
156
                        "access to parent\n", 0, 0, 0 );
 
157
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
 
158
                rs->sr_text = "no write access to parent";
 
159
                goto return_results;
 
160
        }
 
161
 
 
162
        rs->sr_err = ndb_entry_get_data( op, &NA, 1 );
 
163
 
 
164
        rs->sr_err = access_allowed( op, &e,
 
165
                entry, NULL, ACL_WDEL, NULL );
 
166
 
 
167
        if ( !rs->sr_err  ) {
 
168
                Debug( LDAP_DEBUG_TRACE,
 
169
                        "<=- " LDAP_XSTRING(ndb_back_delete) ": no write access "
 
170
                        "to entry\n", 0, 0, 0 );
 
171
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
 
172
                rs->sr_text = "no write access to entry";
 
173
                goto return_results;
 
174
        }
 
175
 
 
176
        if ( !manageDSAit && is_entry_referral( &e ) ) {
 
177
                /* entry is a referral, don't allow delete */
 
178
                rs->sr_ref = get_entry_referrals( op, &e );
 
179
 
 
180
                Debug( LDAP_DEBUG_TRACE,
 
181
                        LDAP_XSTRING(ndb_back_delete) ": entry is referral\n",
 
182
                        0, 0, 0 );
 
183
 
 
184
                rs->sr_err = LDAP_REFERRAL;
 
185
                rs->sr_matched = e.e_name.bv_val;
 
186
                rs->sr_flags = REP_REF_MUSTBEFREED;
 
187
                goto return_results;
 
188
        }
 
189
 
 
190
        if ( get_assert( op ) &&
 
191
                ( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE ))
 
192
        {
 
193
                rs->sr_err = LDAP_ASSERTION_FAILED;
 
194
                goto return_results;
 
195
        }
 
196
 
 
197
        /* pre-read */
 
198
        if( op->o_preread ) {
 
199
                if( preread_ctrl == NULL ) {
 
200
                        preread_ctrl = &ctrls[num_ctrls++];
 
201
                        ctrls[num_ctrls] = NULL;
 
202
                }
 
203
                if( slap_read_controls( op, rs, &e,
 
204
                        &slap_pre_read_bv, preread_ctrl ) )
 
205
                {
 
206
                        Debug( LDAP_DEBUG_TRACE,
 
207
                                "<=- " LDAP_XSTRING(ndb_back_delete) ": pre-read "
 
208
                                "failed!\n", 0, 0, 0 );
 
209
                        if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
 
210
                                /* FIXME: is it correct to abort
 
211
                                 * operation if control fails? */
 
212
                                goto return_results;
 
213
                        }
 
214
                }
 
215
        }
 
216
 
 
217
        /* Can't do it if we have kids */
 
218
        rs->sr_err = ndb_has_children( &NA, &rc );
 
219
        if ( rs->sr_err ) {
 
220
                Debug(LDAP_DEBUG_ARGS,
 
221
                        "<=- " LDAP_XSTRING(ndb_back_delete)
 
222
                        ": has_children failed: %s (%d)\n",
 
223
                        NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
 
224
                rs->sr_err = LDAP_OTHER;
 
225
                rs->sr_text = "internal error";
 
226
                goto return_results;
 
227
        }
 
228
        if ( rc == LDAP_COMPARE_TRUE ) {
 
229
                Debug(LDAP_DEBUG_ARGS,
 
230
                        "<=- " LDAP_XSTRING(ndb_back_delete)
 
231
                        ": non-leaf %s\n",
 
232
                        op->o_req_dn.bv_val, 0, 0);
 
233
                rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
 
234
                rs->sr_text = "subordinate objects must be deleted first";
 
235
                goto return_results;
 
236
        }
 
237
 
 
238
        /* delete info */
 
239
        rs->sr_err = ndb_entry_del_info( op->o_bd, &NA );
 
240
        if ( rs->sr_err != 0 ) {
 
241
                Debug(LDAP_DEBUG_TRACE,
 
242
                        "<=- " LDAP_XSTRING(ndb_back_delete) ": del_info failed: %s (%d)\n",
 
243
                        NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
 
244
                rs->sr_text = "DN index delete failed";
 
245
                rs->sr_err = LDAP_OTHER;
 
246
                goto return_results;
 
247
        }
 
248
 
 
249
        /* delete data */
 
250
        rs->sr_err = ndb_entry_del_data( op->o_bd, &NA );
 
251
        if ( rs->sr_err != 0 ) {
 
252
                Debug( LDAP_DEBUG_TRACE,
 
253
                        "<=- " LDAP_XSTRING(ndb_back_delete) ": del_data failed: %s (%d)\n",
 
254
                        NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 );
 
255
                rs->sr_text = "entry delete failed";
 
256
                rs->sr_err = LDAP_OTHER;
 
257
                goto return_results;
 
258
        }
 
259
 
 
260
        if( op->o_noop ) {
 
261
                if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
 
262
                        NdbOperation::AbortOnError, 1 )) != 0 ) {
 
263
                        rs->sr_text = "txn (no-op) failed";
 
264
                } else {
 
265
                        rs->sr_err = LDAP_X_NO_OPERATION;
 
266
                }
 
267
        } else {
 
268
                if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
 
269
                        NdbOperation::AbortOnError, 1 )) != 0 ) {
 
270
                        rs->sr_text = "txn_commit failed";
 
271
                } else {
 
272
                        rs->sr_err = LDAP_SUCCESS;
 
273
                }
 
274
        }
 
275
 
 
276
        if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
 
277
                Debug( LDAP_DEBUG_TRACE,
 
278
                        LDAP_XSTRING(ndb_back_delete) ": txn_%s failed: %s (%d)\n",
 
279
                        op->o_noop ? "abort (no-op)" : "commit",
 
280
                        NA.txn->getNdbError().message, NA.txn->getNdbError().code );
 
281
                rs->sr_err = LDAP_OTHER;
 
282
                rs->sr_text = "commit failed";
 
283
 
 
284
                goto return_results;
 
285
        }
 
286
        NA.txn->close();
 
287
        NA.txn = NULL;
 
288
 
 
289
        Debug( LDAP_DEBUG_TRACE,
 
290
                LDAP_XSTRING(ndb_back_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
 
291
                op->o_noop ? " (no-op)" : "",
 
292
                e.e_id, op->o_req_dn.bv_val );
 
293
        rs->sr_err = LDAP_SUCCESS;
 
294
        rs->sr_text = NULL;
 
295
        if( num_ctrls ) rs->sr_ctrls = ctrls;
 
296
 
 
297
return_results:
 
298
        if ( NA.ocs ) {
 
299
                ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
 
300
                NA.ocs = NULL;
 
301
        }
 
302
 
 
303
        /* free entry */
 
304
        if( e.e_attrs != NULL ) {
 
305
                attrs_free( e.e_attrs );
 
306
                e.e_attrs = NULL;
 
307
        }
 
308
 
 
309
        if( NA.txn != NULL ) {
 
310
                NA.txn->execute( Rollback );
 
311
                NA.txn->close();
 
312
        }
 
313
 
 
314
        send_ldap_result( op, rs );
 
315
        slap_graduate_commit_csn( op );
 
316
 
 
317
        if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
 
318
                slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
 
319
                slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
 
320
        }
 
321
        return rs->sr_err;
 
322
}