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

« back to all changes in this revision

Viewing changes to servers/slapd/back-ndb/add.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
/* add.cpp - ldap NDB back-end add routine */
 
2
/* $OpenLDAP: pkg/ldap/servers/slapd/back-ndb/add.cpp,v 1.3.2.4 2009/02/05 19:35:54 quanah 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 "back-ndb.h"
 
27
 
 
28
extern "C" int
 
29
ndb_back_add(Operation *op, SlapReply *rs )
 
30
{
 
31
        struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
 
32
        Entry           p = {0};
 
33
        Attribute       poc;
 
34
        char textbuf[SLAP_TEXT_BUFLEN];
 
35
        size_t textlen = sizeof textbuf;
 
36
        AttributeDescription *children = slap_schema.si_ad_children;
 
37
        AttributeDescription *entry = slap_schema.si_ad_entry;
 
38
        NdbArgs NA;
 
39
        NdbRdns rdns;
 
40
        struct berval matched;
 
41
        struct berval pdn, pndn;
 
42
 
 
43
        int             num_retries = 0;
 
44
        int             success;
 
45
 
 
46
        LDAPControl **postread_ctrl = NULL;
 
47
        LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
 
48
        int num_ctrls = 0;
 
49
 
 
50
        Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(ndb_back_add) ": %s\n",
 
51
                op->oq_add.rs_e->e_name.bv_val, 0, 0);
 
52
 
 
53
        ctrls[num_ctrls] = 0;
 
54
 
 
55
        /* check entry's schema */
 
56
        rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL,
 
57
                get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
 
58
        if ( rs->sr_err != LDAP_SUCCESS ) {
 
59
                Debug( LDAP_DEBUG_TRACE,
 
60
                        LDAP_XSTRING(ndb_back_add) ": entry failed schema check: "
 
61
                        "%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
 
62
                goto return_results;
 
63
        }
 
64
 
 
65
        /* add opattrs to shadow as well, only missing attrs will actually
 
66
         * be added; helps compatibility with older OL versions */
 
67
        rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
 
68
        if ( rs->sr_err != LDAP_SUCCESS ) {
 
69
                Debug( LDAP_DEBUG_TRACE,
 
70
                        LDAP_XSTRING(ndb_back_add) ": entry failed op attrs add: "
 
71
                        "%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
 
72
                goto return_results;
 
73
        }
 
74
 
 
75
        /* Get our NDB handle */
 
76
        rs->sr_err = ndb_thread_handle( op, &NA.ndb );
 
77
 
 
78
        /*
 
79
         * Get the parent dn and see if the corresponding entry exists.
 
80
         */
 
81
        if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
 
82
                pdn = slap_empty_bv;
 
83
                pndn = slap_empty_bv;
 
84
        } else {
 
85
                dnParent( &op->ora_e->e_name, &pdn );
 
86
                dnParent( &op->ora_e->e_nname, &pndn );
 
87
        }
 
88
        p.e_name = op->ora_e->e_name;
 
89
        p.e_nname = op->ora_e->e_nname;
 
90
 
 
91
        op->ora_e->e_id = NOID;
 
92
        rdns.nr_num = 0;
 
93
        NA.rdns = &rdns;
 
94
 
 
95
        if( 0 ) {
 
96
retry:  /* transaction retry */
 
97
                NA.txn->close();
 
98
                NA.txn = NULL;
 
99
                if ( op->o_abandon ) {
 
100
                        rs->sr_err = SLAPD_ABANDON;
 
101
                        goto return_results;
 
102
                }
 
103
                ndb_trans_backoff( ++num_retries );
 
104
        }
 
105
 
 
106
        NA.txn = NA.ndb->startTransaction();
 
107
        rs->sr_text = NULL;
 
108
        if( !NA.txn ) {
 
109
                Debug( LDAP_DEBUG_TRACE,
 
110
                        LDAP_XSTRING(ndb_back_add) ": startTransaction failed: %s (%d)\n",
 
111
                        NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
 
112
                rs->sr_err = LDAP_OTHER;
 
113
                rs->sr_text = "internal error";
 
114
                goto return_results;
 
115
        }
 
116
 
 
117
        /* get entry or parent */
 
118
        NA.e = &p;
 
119
        NA.ocs = NULL;
 
120
        rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
 
121
        switch( rs->sr_err ) {
 
122
        case 0:
 
123
                rs->sr_err = LDAP_ALREADY_EXISTS;
 
124
                goto return_results;
 
125
        case LDAP_NO_SUCH_OBJECT:
 
126
                break;
 
127
#if 0
 
128
        case DB_LOCK_DEADLOCK:
 
129
        case DB_LOCK_NOTGRANTED:
 
130
                goto retry;
 
131
#endif
 
132
        case LDAP_BUSY:
 
133
                rs->sr_text = "ldap server busy";
 
134
                goto return_results;
 
135
        default:
 
136
                rs->sr_err = LDAP_OTHER;
 
137
                rs->sr_text = "internal error";
 
138
                goto return_results;
 
139
        }
 
140
 
 
141
        if ( NA.ocs ) {
 
142
                int i;
 
143
                for ( i=0; !BER_BVISNULL( &NA.ocs[i] ); i++ );
 
144
                poc.a_numvals = i;
 
145
                poc.a_desc = slap_schema.si_ad_objectClass;
 
146
                poc.a_vals = NA.ocs;
 
147
                poc.a_nvals = poc.a_vals;
 
148
                poc.a_next = NULL;
 
149
                p.e_attrs = &poc;
 
150
        }
 
151
 
 
152
        if ( ber_bvstrcasecmp( &pndn, &matched ) ) {
 
153
                rs->sr_matched = matched.bv_val;
 
154
                Debug( LDAP_DEBUG_TRACE,
 
155
                        LDAP_XSTRING(ndb_back_add) ": parent "
 
156
                        "does not exist\n", 0, 0, 0 );
 
157
 
 
158
                rs->sr_text = "parent does not exist";
 
159
                rs->sr_err = LDAP_NO_SUCH_OBJECT;
 
160
                if ( p.e_attrs && is_entry_referral( &p )) {
 
161
is_ref:                 p.e_attrs = NULL;
 
162
                        ndb_entry_get_data( op, &NA, 0 );
 
163
                        rs->sr_ref = get_entry_referrals( op, &p );
 
164
                        rs->sr_err = LDAP_REFERRAL;
 
165
                        rs->sr_flags = REP_REF_MUSTBEFREED;
 
166
                        attrs_free( p.e_attrs );
 
167
                        p.e_attrs = NULL;
 
168
                }
 
169
                goto return_results;
 
170
        }
 
171
 
 
172
        p.e_name = pdn;
 
173
        p.e_nname = pndn;
 
174
        rs->sr_err = access_allowed( op, &p,
 
175
                children, NULL, ACL_WADD, NULL );
 
176
 
 
177
        if ( ! rs->sr_err ) {
 
178
                Debug( LDAP_DEBUG_TRACE,
 
179
                        LDAP_XSTRING(ndb_back_add) ": no write access to parent\n",
 
180
                        0, 0, 0 );
 
181
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
 
182
                rs->sr_text = "no write access to parent";
 
183
                goto return_results;
 
184
        }
 
185
 
 
186
        if ( NA.ocs ) {
 
187
                if ( is_entry_subentry( &p )) {
 
188
                        /* parent is a subentry, don't allow add */
 
189
                        Debug( LDAP_DEBUG_TRACE,
 
190
                                LDAP_XSTRING(ndb_back_add) ": parent is subentry\n",
 
191
                                0, 0, 0 );
 
192
                        rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
 
193
                        rs->sr_text = "parent is a subentry";
 
194
                        goto return_results;
 
195
                }
 
196
 
 
197
                if ( is_entry_alias( &p ) ) {
 
198
                        /* parent is an alias, don't allow add */
 
199
                        Debug( LDAP_DEBUG_TRACE,
 
200
                                LDAP_XSTRING(ndb_back_add) ": parent is alias\n",
 
201
                                0, 0, 0 );
 
202
                        rs->sr_err = LDAP_ALIAS_PROBLEM;
 
203
                        rs->sr_text = "parent is an alias";
 
204
                        goto return_results;
 
205
                }
 
206
 
 
207
                if ( is_entry_referral( &p ) ) {
 
208
                        /* parent is a referral, don't allow add */
 
209
                        rs->sr_matched = p.e_name.bv_val;
 
210
                        goto is_ref;
 
211
                }
 
212
        }
 
213
 
 
214
        rs->sr_err = access_allowed( op, op->ora_e,
 
215
                entry, NULL, ACL_WADD, NULL );
 
216
 
 
217
        if ( ! rs->sr_err ) {
 
218
                Debug( LDAP_DEBUG_TRACE,
 
219
                        LDAP_XSTRING(ndb_back_add) ": no write access to entry\n",
 
220
                        0, 0, 0 );
 
221
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
 
222
                rs->sr_text = "no write access to entry";
 
223
                goto return_results;;
 
224
        }
 
225
 
 
226
        /* 
 
227
         * Check ACL for attribute write access
 
228
         */
 
229
        if (!acl_check_modlist(op, op->ora_e, op->ora_modlist)) {
 
230
                Debug( LDAP_DEBUG_TRACE,
 
231
                        LDAP_XSTRING(bdb_add) ": no write access to attribute\n",
 
232
                        0, 0, 0 );
 
233
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
 
234
                rs->sr_text = "no write access to attribute";
 
235
                goto return_results;;
 
236
        }
 
237
 
 
238
 
 
239
        /* acquire entry ID */
 
240
        if ( op->ora_e->e_id == NOID ) {
 
241
                rs->sr_err = ndb_next_id( op->o_bd, NA.ndb, &op->ora_e->e_id );
 
242
                if( rs->sr_err != 0 ) {
 
243
                        Debug( LDAP_DEBUG_TRACE,
 
244
                                LDAP_XSTRING(ndb_back_add) ": next_id failed (%d)\n",
 
245
                                rs->sr_err, 0, 0 );
 
246
                        rs->sr_err = LDAP_OTHER;
 
247
                        rs->sr_text = "internal error";
 
248
                        goto return_results;
 
249
                }
 
250
        }
 
251
 
 
252
        if ( matched.bv_val )
 
253
                rdns.nr_num++;
 
254
        NA.e = op->ora_e;
 
255
        /* dn2id index */
 
256
        rs->sr_err = ndb_entry_put_info( op->o_bd, &NA, 0 );
 
257
        if ( rs->sr_err ) {
 
258
                Debug( LDAP_DEBUG_TRACE,
 
259
                        LDAP_XSTRING(ndb_back_add) ": ndb_entry_put_info failed (%d)\n",
 
260
                        rs->sr_err, 0, 0 );
 
261
                rs->sr_text = "internal error";
 
262
                goto return_results;
 
263
        }
 
264
 
 
265
        /* id2entry index */
 
266
        rs->sr_err = ndb_entry_put_data( op->o_bd, &NA );
 
267
        if ( rs->sr_err ) {
 
268
                Debug( LDAP_DEBUG_TRACE,
 
269
                        LDAP_XSTRING(ndb_back_add) ": ndb_entry_put_data failed (%d) %s(%d)\n",
 
270
                        rs->sr_err, NA.txn->getNdbError().message, NA.txn->getNdbError().code );
 
271
                rs->sr_text = "internal error";
 
272
                goto return_results;
 
273
        }
 
274
 
 
275
        /* post-read */
 
276
        if( op->o_postread ) {
 
277
                if( postread_ctrl == NULL ) {
 
278
                        postread_ctrl = &ctrls[num_ctrls++];
 
279
                        ctrls[num_ctrls] = NULL;
 
280
                }
 
281
                if ( slap_read_controls( op, rs, op->oq_add.rs_e,
 
282
                        &slap_post_read_bv, postread_ctrl ) )
 
283
                {
 
284
                        Debug( LDAP_DEBUG_TRACE,
 
285
                                "<=- " LDAP_XSTRING(ndb_back_add) ": post-read "
 
286
                                "failed!\n", 0, 0, 0 );
 
287
                        if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
 
288
                                /* FIXME: is it correct to abort
 
289
                                 * operation if control fails? */
 
290
                                goto return_results;
 
291
                        }
 
292
                }
 
293
        }
 
294
 
 
295
        if ( op->o_noop ) {
 
296
                if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback,
 
297
                        NdbOperation::AbortOnError, 1 )) != 0 ) {
 
298
                        rs->sr_text = "txn (no-op) failed";
 
299
                } else {
 
300
                        rs->sr_err = LDAP_X_NO_OPERATION;
 
301
                }
 
302
 
 
303
        } else {
 
304
                if(( rs->sr_err=NA.txn->execute( NdbTransaction::Commit,
 
305
                        NdbOperation::AbortOnError, 1 )) != 0 ) {
 
306
                        rs->sr_text = "txn_commit failed";
 
307
                } else {
 
308
                        rs->sr_err = LDAP_SUCCESS;
 
309
                }
 
310
        }
 
311
 
 
312
        if ( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) {
 
313
                Debug( LDAP_DEBUG_TRACE,
 
314
                        LDAP_XSTRING(ndb_back_add) ": %s : %s (%d)\n",
 
315
                        rs->sr_text, NA.txn->getNdbError().message, NA.txn->getNdbError().code );
 
316
                rs->sr_err = LDAP_OTHER;
 
317
                goto return_results;
 
318
        }
 
319
        NA.txn->close();
 
320
        NA.txn = NULL;
 
321
 
 
322
        Debug(LDAP_DEBUG_TRACE,
 
323
                LDAP_XSTRING(ndb_back_add) ": added%s id=%08lx dn=\"%s\"\n",
 
324
                op->o_noop ? " (no-op)" : "",
 
325
                op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
 
326
 
 
327
        rs->sr_text = NULL;
 
328
        if( num_ctrls ) rs->sr_ctrls = ctrls;
 
329
 
 
330
return_results:
 
331
        success = rs->sr_err;
 
332
        send_ldap_result( op, rs );
 
333
        slap_graduate_commit_csn( op );
 
334
 
 
335
        if( NA.txn != NULL ) {
 
336
                NA.txn->execute( Rollback );
 
337
                NA.txn->close();
 
338
        }
 
339
 
 
340
        if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
 
341
                slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
 
342
                slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
 
343
        }
 
344
 
 
345
        return rs->sr_err;
 
346
}