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

« back to all changes in this revision

Viewing changes to servers/slapd/overlays/collect.c

  • 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
1
/* collect.c - Demonstration of overlay code */
2
 
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/collect.c,v 1.5.2.4 2008/02/11 23:26:48 kurt Exp $ */
 
2
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/collect.c,v 1.5.2.8 2009/01/22 00:01:12 kurt Exp $ */
3
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
4
 *
5
 
 * Copyright 2003-2008 The OpenLDAP Foundation.
 
5
 * Copyright 2003-2009 The OpenLDAP Foundation.
6
6
 * Portions Copyright 2003 Howard Chu.
7
7
 * All rights reserved.
8
8
 *
31
31
#include "slap.h"
32
32
#include "config.h"
33
33
 
 
34
#include "lutil.h"
 
35
 
34
36
/* This is a cheap hack to implement a collective attribute.
35
37
 *
36
38
 * This demonstration overlay looks for a specified attribute in an
43
45
typedef struct collect_info {
44
46
        struct collect_info *ci_next;
45
47
        struct berval ci_dn;
46
 
        AttributeDescription *ci_ad;
 
48
        int ci_ad_num;
 
49
        AttributeDescription *ci_ad[1];
47
50
} collect_info;
48
51
 
 
52
/*
 
53
 * inserts a collect_info into on->on_bi.bi_private taking into account
 
54
 * order. this means longer dn's (i.e. more specific dn's) will be found
 
55
 * first when searching, allowing some limited overlap of dn's
 
56
 */
 
57
static void
 
58
insert_ordered( slap_overinst *on, collect_info *ci ) {
 
59
        collect_info *find = on->on_bi.bi_private;
 
60
        collect_info *prev = NULL;
 
61
        int found = 0;
 
62
 
 
63
        while (!found) {
 
64
                if (find == NULL) {
 
65
                        if (prev == NULL) {
 
66
                                /* base case - empty list */
 
67
                                on->on_bi.bi_private = ci;
 
68
                                ci->ci_next = NULL;
 
69
                        } else {
 
70
                                /* final case - end of list */
 
71
                                prev->ci_next = ci;
 
72
                                ci->ci_next = NULL;
 
73
                        }
 
74
                        found = 1;
 
75
                } else if (find->ci_dn.bv_len <= ci->ci_dn.bv_len) { 
 
76
                        /* insert into list here */
 
77
                        if (prev == NULL) {
 
78
                                /* entry is head of list */
 
79
                                ci->ci_next = on->on_bi.bi_private;
 
80
                                on->on_bi.bi_private = ci;
 
81
                        } else {
 
82
                                /* entry is not head of list */
 
83
                                prev->ci_next = ci;
 
84
                                ci->ci_next = find;
 
85
                        }
 
86
                        found = 1;
 
87
                } else {
 
88
                        /* keep looking */
 
89
                        prev = find;
 
90
                        find = find->ci_next;
 
91
                }
 
92
        }
 
93
}
 
94
 
49
95
static int
50
96
collect_cf( ConfigArgs *c )
51
97
{
52
98
        slap_overinst *on = (slap_overinst *)c->bi;
53
 
        int rc = 1;
 
99
        int rc = 1, idx;
54
100
 
55
101
        switch( c->op ) {
56
102
        case SLAP_CONFIG_EMIT:
58
104
                collect_info *ci;
59
105
                for ( ci = on->on_bi.bi_private; ci; ci = ci->ci_next ) {
60
106
                        struct berval bv;
 
107
                        char *ptr;
61
108
                        int len;
62
109
 
63
 
                        bv.bv_len = ci->ci_dn.bv_len + STRLENOF("\"\" ") +
64
 
                                ci->ci_ad->ad_cname.bv_len;
 
110
                        /* calculate the length & malloc memory */
 
111
                        bv.bv_len = ci->ci_dn.bv_len + STRLENOF("\"\" ");
 
112
                        for (idx=0; idx<ci->ci_ad_num; idx++) {
 
113
                                bv.bv_len += ci->ci_ad[idx]->ad_cname.bv_len;
 
114
                                if (idx<(ci->ci_ad_num-1)) { 
 
115
                                        bv.bv_len++;
 
116
                                }
 
117
                        }
65
118
                        bv.bv_val = ch_malloc( bv.bv_len + 1 );
66
 
                        len = snprintf( bv.bv_val, bv.bv_len + 1, "\"%s\" %s",
67
 
                                ci->ci_dn.bv_val, ci->ci_ad->ad_cname.bv_val );
68
 
                        assert( len == bv.bv_len );
 
119
 
 
120
                        /* copy the value and update len */
 
121
                        len = snprintf( bv.bv_val, bv.bv_len + 1, "\"%s\" ", 
 
122
                                ci->ci_dn.bv_val);
 
123
                        ptr = bv.bv_val + len;
 
124
                        for (idx=0; idx<ci->ci_ad_num; idx++) {
 
125
                                ptr = lutil_strncopy( ptr,
 
126
                                        ci->ci_ad[idx]->ad_cname.bv_val,
 
127
                                        ci->ci_ad[idx]->ad_cname.bv_len);
 
128
                                if (idx<(ci->ci_ad_num-1)) {
 
129
                                        *ptr++ = ',';
 
130
                                }
 
131
                        }
 
132
                        *ptr = '\0';
 
133
                        bv.bv_len = ptr - bv.bv_val;
 
134
 
69
135
                        ber_bvarray_add( &c->rvalue_vals, &bv );
70
136
                        rc = 0;
71
137
                }
98
164
                collect_info *ci;
99
165
                struct berval bv, dn;
100
166
                const char *text;
101
 
                AttributeDescription *ad = NULL;
102
 
 
 
167
                int idx, count=0;
 
168
                char *arg;
 
169
 
 
170
                /* count delimiters in attribute argument */
 
171
                arg = strtok(c->argv[2], ",");
 
172
                while (arg!=NULL) {
 
173
                        count++;
 
174
                        arg = strtok(NULL, ",");
 
175
                }
 
176
 
 
177
                /* allocate config info with room for attribute array */
 
178
                ci = ch_malloc( sizeof( collect_info ) +
 
179
                        sizeof( AttributeDescription * ) * count );
 
180
 
 
181
                /* validate and normalize dn */
103
182
                ber_str2bv( c->argv[1], 0, 0, &bv );
104
183
                if ( dnNormalize( 0, NULL, NULL, &bv, &dn, NULL ) ) {
105
184
                        snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: \"%s\"",
108
187
                                "%s: %s\n", c->log, c->cr_msg, 0 );
109
188
                        return ARG_BAD_CONF;
110
189
                }
111
 
                if ( slap_str2ad( c->argv[2], &ad, &text ) ) {
112
 
                        snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s attribute description unknown: \"%s\"",
113
 
                                c->argv[0], c->argv[2] );
114
 
                        Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
115
 
                                "%s: %s\n", c->log, c->cr_msg, 0 );
116
 
                        return ARG_BAD_CONF;
 
190
 
 
191
                /* load attribute description for attribute list */
 
192
                arg = c->argv[2];
 
193
                for( idx=0; idx<count; idx++) {
 
194
                        ci->ci_ad[idx] = NULL;
 
195
 
 
196
                        if ( slap_str2ad( arg, &ci->ci_ad[idx], &text ) ) {
 
197
                                snprintf( c->cr_msg, sizeof( c->cr_msg ), 
 
198
                                        "%s attribute description unknown: \"%s\"",
 
199
                                        c->argv[0], arg);
 
200
                                Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
 
201
                                        "%s: %s\n", c->log, c->cr_msg, 0 );
 
202
                                return ARG_BAD_CONF;
 
203
                        }
 
204
                        while(*arg!='\0') {
 
205
                                arg++; /* skip to end of argument */
 
206
                        }
 
207
                        if (idx<count-1) {
 
208
                                arg++; /* skip inner delimiters */
 
209
                        }
117
210
                }
118
211
 
119
212
                /* The on->on_bi.bi_private pointer can be used for
120
213
                 * anything this instance of the overlay needs.
121
214
                 */
122
 
                ci = ch_malloc( sizeof( collect_info ));
123
 
                ci->ci_ad = ad;
 
215
                ci->ci_ad[count] = NULL;
 
216
                ci->ci_ad_num = count;
124
217
                ci->ci_dn = dn;
125
 
                ci->ci_next = on->on_bi.bi_private;
126
 
                on->on_bi.bi_private = ci;
 
218
 
 
219
                /* creates list of ci's ordered by dn length */ 
 
220
                insert_ordered ( on, ci );
 
221
 
127
222
                rc = 0;
128
223
                }
129
224
        }
167
262
}
168
263
 
169
264
static int
 
265
collect_modify( Operation *op, SlapReply *rs)
 
266
{
 
267
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
 
268
        collect_info *ci = on->on_bi.bi_private;
 
269
        Modifications *ml;
 
270
        char errMsg[100];
 
271
        int idx;
 
272
 
 
273
        for ( ml = op->orm_modlist; ml != NULL; ml = ml->sml_next) {
 
274
                for (; ci; ci=ci->ci_next ) {
 
275
                        /* Is this entry an ancestor of this collectinfo ? */
 
276
                        if (!dnIsSuffix(&op->o_req_ndn, &ci->ci_dn)) {
 
277
                                /* this collectinfo does not match */
 
278
                                continue;
 
279
                        }
 
280
 
 
281
                        /* Is this entry the same as the template DN ? */
 
282
                        if ( dn_match(&op->o_req_ndn, &ci->ci_dn)) {
 
283
                                /* all changes in this ci are allowed */
 
284
                                continue;
 
285
                        }
 
286
 
 
287
                        /* check for collect attributes - disallow modify if present */
 
288
                        for(idx=0; idx<ci->ci_ad_num; idx++) {
 
289
                                if (ml->sml_desc == ci->ci_ad[idx]) {
 
290
                                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
 
291
                                        snprintf( errMsg, sizeof( errMsg ), 
 
292
                                                "cannot change virtual attribute '%s'",
 
293
                                                ci->ci_ad[idx]->ad_cname.bv_val);
 
294
                                        rs->sr_text = errMsg;
 
295
                                        send_ldap_result( op, rs );
 
296
                                        return rs->sr_err;
 
297
                                }
 
298
                        }
 
299
                }
 
300
 
 
301
        }
 
302
 
 
303
        return SLAP_CB_CONTINUE;
 
304
}
 
305
 
 
306
static int
170
307
collect_response( Operation *op, SlapReply *rs )
171
308
{
172
309
        slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
181
318
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
182
319
 
183
320
                for (; ci; ci=ci->ci_next ) {
184
 
                        BerVarray vals = NULL;
185
 
 
186
 
                        /* Is our configured entry an ancestor of this one? */
187
 
                        if ( !dnIsSuffix( &rs->sr_entry->e_nname, &ci->ci_dn ))
188
 
                                continue;
189
 
 
190
 
                        /* Extract the values of the desired attribute from
191
 
                         * the ancestor entry
192
 
                         */
193
 
                        rc = backend_attribute( op, NULL, &ci->ci_dn, ci->ci_ad, &vals, ACL_READ );
194
 
 
195
 
                        /* If there are any values, merge them into the
196
 
                         * current entry
197
 
                         */
198
 
                        if ( vals ) {
199
 
                                /* The current entry may live in a cache, so
200
 
                                 * don't modify it directly. Make a copy and
201
 
                                 * work with that instead.
202
 
                                 */
203
 
                                if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) {
204
 
                                        rs->sr_entry = entry_dup( rs->sr_entry );
205
 
                                        rs->sr_flags |= REP_ENTRY_MODIFIABLE |
206
 
                                                REP_ENTRY_MUSTBEFREED;
 
321
                        int idx=0;
 
322
 
 
323
                        /* Is this entry an ancestor of this collectinfo ? */
 
324
                        if (!dnIsSuffix(&rs->sr_entry->e_nname, &ci->ci_dn)) {
 
325
                                /* collectinfo does not match */
 
326
                                continue;
 
327
                        }
 
328
 
 
329
                        /* Is this entry the same as the template DN ? */
 
330
                        if ( dn_match(&rs->sr_entry->e_nname, &ci->ci_dn)) {
 
331
                                /* dont apply change to parent */
 
332
                                continue;
 
333
                        }
 
334
 
 
335
                        /* The current entry may live in a cache, so
 
336
                        * don't modify it directly. Make a copy and
 
337
                        * work with that instead.
 
338
                        */
 
339
                        if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) {
 
340
                                rs->sr_entry = entry_dup( rs->sr_entry );
 
341
                                rs->sr_flags |= REP_ENTRY_MODIFIABLE |
 
342
                                        REP_ENTRY_MUSTBEFREED;
 
343
                        }
 
344
 
 
345
                        /* Loop for each attribute in this collectinfo */
 
346
                        for(idx=0; idx<ci->ci_ad_num; idx++) {
 
347
                                BerVarray vals = NULL;
 
348
 
 
349
                                /* Extract the values of the desired attribute from
 
350
                                 * the ancestor entry */
 
351
                                rc = backend_attribute( op, NULL, &ci->ci_dn, 
 
352
                                        ci->ci_ad[idx], &vals, ACL_READ );
 
353
 
 
354
                                /* If there are any values, merge them into the
 
355
                                 * current search result
 
356
                                 */
 
357
                                if ( vals ) {
 
358
                                        attr_merge( rs->sr_entry, ci->ci_ad[idx], 
 
359
                                                vals, NULL );
 
360
                                        ber_bvarray_free_x( vals, op->o_tmpmemctx );
207
361
                                }
208
 
                                attr_merge( rs->sr_entry, ci->ci_ad, vals, NULL );
209
 
                                ber_bvarray_free_x( vals, op->o_tmpmemctx );
210
362
                        }
211
363
                }
212
364
        }
 
365
 
213
366
        /* Default is to just fall through to the normal processing */
214
367
        return SLAP_CB_CONTINUE;
215
368
}
221
374
 
222
375
        collect.on_bi.bi_type = "collect";
223
376
        collect.on_bi.bi_db_destroy = collect_destroy;
 
377
        collect.on_bi.bi_op_modify = collect_modify;
224
378
        collect.on_response = collect_response;
225
379
 
226
380
        collect.on_bi.bi_cf_ocs = collectocs;