~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to contrib/slapd-modules/autogroup/autogroup.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* autogroup.c - automatic group overlay */
 
2
/* $OpenLDAP: pkg/ldap/contrib/slapd-modules/autogroup/autogroup.c,v 1.2.2.1 2008/02/08 23:00:43 quanah Exp $ */
 
3
/*
 
4
 * Copyright 2007 Michał Szulczyński.
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted only as authorized by the OpenLDAP
 
9
 * Public License.
 
10
 *
 
11
 * A copy of this license is available in the file LICENSE in the
 
12
 * top-level directory of the distribution or, alternatively, at
 
13
 * <http://www.OpenLDAP.org/license.html>.
 
14
 */
 
15
 
 
16
#include "portable.h"
 
17
 
 
18
#include <stdio.h>
 
19
 
 
20
#include <ac/string.h>
 
21
 
 
22
#include "slap.h"
 
23
#include "config.h"
 
24
#include "lutil.h"
 
25
 
 
26
/* Filter represents the memberURL of a group. */
 
27
typedef struct autogroup_filter_t {
 
28
        struct berval                   agf_dn; /* The base DN in memberURL */
 
29
        struct berval                   agf_ndn;
 
30
        struct berval                   agf_filterstr;
 
31
        Filter                          *agf_filter;
 
32
        int                             agf_scope;
 
33
        struct autogroup_filter_t       *agf_next;
 
34
} autogroup_filter_t;
 
35
 
 
36
/* Description of group attributes. */
 
37
typedef struct autogroup_def_t {
 
38
        ObjectClass             *agd_oc;
 
39
        AttributeDescription    *agd_member_url_ad;
 
40
        AttributeDescription    *agd_member_ad;
 
41
        struct autogroup_def_t  *agd_next;
 
42
} autogroup_def_t;
 
43
 
 
44
/* Represents the group entry. */
 
45
typedef struct autogroup_entry_t {
 
46
        BerValue                age_dn;
 
47
        BerValue                age_ndn;
 
48
        autogroup_filter_t      *age_filter; /* List of filters made from memberURLs */
 
49
        autogroup_def_t         *age_def; /* Attribute definition */
 
50
        ldap_pvt_thread_mutex_t age_mutex;
 
51
        struct autogroup_entry_t        *age_next;
 
52
} autogroup_entry_t;
 
53
 
 
54
/* Holds pointers to attribute definitions and groups. */
 
55
typedef struct autogroup_info_t {
 
56
        autogroup_def_t         *agi_def;       /* Group attributes definitions. */
 
57
        autogroup_entry_t       *agi_entry;     /* Group entries.  */
 
58
        ldap_pvt_thread_mutex_t agi_mutex;
 
59
} autogroup_info_t;
 
60
 
 
61
/* Search callback for adding groups initially. */
 
62
typedef struct autogroup_sc_t {
 
63
        autogroup_info_t                *ags_info;      /* Group definitions and entries.  */
 
64
        autogroup_def_t         *ags_def;       /* Attributes definition of the group being added. */
 
65
} autogroup_sc_t;
 
66
 
 
67
/* Used for adding members, found when searching, to a group. */
 
68
typedef struct autogroup_ga_t {
 
69
        autogroup_entry_t       *agg_group;     /* The group to which the members will be added. */
 
70
        Entry                   *agg_entry;     /* Used in autogroup_member_search_cb to modify 
 
71
                                                this entry with the search results. */
 
72
 
 
73
        Modifications           *agg_mod;       /* Used in autogroup_member_search_modify_cb to hold the 
 
74
                                                search results which will be added to the group. */
 
75
 
 
76
        Modifications           *agg_mod_last; /* Used in autogroup_member_search_modify_cb so we don't 
 
77
                                                have to search for the last mod added. */
 
78
} autogroup_ga_t;
 
79
 
 
80
 
 
81
/* 
 
82
**      dn, ndn - the DN of the member to add
 
83
**      age     - the group to which the member DN will be added
 
84
*/
 
85
static int
 
86
autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
 
87
{
 
88
        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
 
89
        Modifications   modlist;
 
90
        SlapReply       sreply = {REP_RESULT};
 
91
        BerValue        vals[ 2 ], nvals[ 2 ];
 
92
        slap_callback   cb = { NULL, slap_null_cb, NULL, NULL };
 
93
        Operation       o = *op;
 
94
 
 
95
        Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_to_group adding <%s> to <%s>\n",
 
96
                dn->bv_val, age->age_dn.bv_val, 0);
 
97
 
 
98
        assert( dn != NULL );
 
99
        assert( ndn != NULL );
 
100
 
 
101
        vals[ 0 ] = *dn;
 
102
        BER_BVZERO( &vals[ 1 ] );
 
103
        nvals[ 0 ] = *ndn;
 
104
        BER_BVZERO( &nvals[ 1 ] );
 
105
 
 
106
        modlist.sml_op = LDAP_MOD_ADD;
 
107
        modlist.sml_desc = age->age_def->agd_member_ad;
 
108
        modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
 
109
        modlist.sml_values = vals;
 
110
        modlist.sml_nvalues = nvals;
 
111
        modlist.sml_numvals = 1;
 
112
        modlist.sml_flags = SLAP_MOD_INTERNAL;
 
113
        modlist.sml_next = NULL;
 
114
 
 
115
        o.o_tag = LDAP_REQ_MODIFY;
 
116
        o.o_callback = &cb;
 
117
        o.orm_modlist = &modlist;
 
118
        o.o_req_dn = age->age_dn;
 
119
        o.o_req_ndn = age->age_ndn;
 
120
        o.o_permissive_modify = 1;
 
121
        o.o_managedsait = SLAP_CONTROL_CRITICAL;
 
122
        o.o_relax = SLAP_CONTROL_CRITICAL;
 
123
 
 
124
        o.o_bd->bd_info = (BackendInfo *)on->on_info;
 
125
        (void)op->o_bd->be_modify( &o, &sreply );
 
126
        o.o_bd->bd_info = (BackendInfo *)on;
 
127
 
 
128
        return sreply.sr_err;
 
129
}
 
130
 
 
131
/*
 
132
** dn,ndn       - the DN to be deleted
 
133
** age          - the group from which the DN will be deleted
 
134
** If we pass a NULL dn and ndn, all members are deleted from the group. 
 
135
*/
 
136
static int
 
137
autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
 
138
{
 
139
        slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
 
140
        Modifications   modlist;
 
141
        SlapReply       sreply = {REP_RESULT};
 
142
        BerValue        vals[ 2 ], nvals[ 2 ];
 
143
        slap_callback   cb = { NULL, slap_null_cb, NULL, NULL };
 
144
        Operation       o = *op;
 
145
 
 
146
        if ( dn == NULL || ndn == NULL ) {
 
147
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing all members from <%s>\n",
 
148
                        age->age_dn.bv_val, 0 ,0);
 
149
 
 
150
                modlist.sml_values = NULL;
 
151
                modlist.sml_nvalues = NULL;
 
152
                modlist.sml_numvals = 0;
 
153
        } else {
 
154
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing <%s> from <%s>\n",
 
155
                        dn->bv_val, age->age_dn.bv_val, 0);
 
156
 
 
157
                vals[ 0 ] = *dn;
 
158
                BER_BVZERO( &vals[ 1 ] );
 
159
                nvals[ 0 ] = *ndn;
 
160
                BER_BVZERO( &nvals[ 1 ] );
 
161
 
 
162
                modlist.sml_values = vals;
 
163
                modlist.sml_nvalues = nvals;
 
164
                modlist.sml_numvals = 1;
 
165
        }
 
166
 
 
167
 
 
168
        modlist.sml_op = LDAP_MOD_DELETE;
 
169
        modlist.sml_desc = age->age_def->agd_member_ad;
 
170
        modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
 
171
        modlist.sml_flags = SLAP_MOD_INTERNAL;
 
172
        modlist.sml_next = NULL;
 
173
 
 
174
        o.o_callback = &cb;
 
175
        o.o_tag = LDAP_REQ_MODIFY;
 
176
        o.orm_modlist = &modlist;
 
177
        o.o_req_dn = age->age_dn;
 
178
        o.o_req_ndn = age->age_ndn;
 
179
        o.o_relax = SLAP_CONTROL_CRITICAL;
 
180
        o.o_managedsait = SLAP_CONTROL_CRITICAL;
 
181
        o.o_permissive_modify = 1;
 
182
 
 
183
        o.o_bd->bd_info = (BackendInfo *)on->on_info;
 
184
        (void)op->o_bd->be_modify( &o, &sreply );
 
185
        o.o_bd->bd_info = (BackendInfo *)on;
 
186
 
 
187
        return sreply.sr_err;
 
188
}
 
189
 
 
190
/* 
 
191
** Callback used to add entries to a group, 
 
192
** which are going to be written in the database
 
193
** (used in bi_op_add)
 
194
** The group is passed in autogroup_ga_t->agg_group
 
195
*/
 
196
static int
 
197
autogroup_member_search_cb( Operation *op, SlapReply *rs )
 
198
{
 
199
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
200
 
 
201
        assert( op->o_tag == LDAP_REQ_SEARCH );
 
202
 
 
203
        if ( rs->sr_type == REP_SEARCH ) {
 
204
                autogroup_ga_t          *agg = (autogroup_ga_t *)op->o_callback->sc_private;
 
205
                autogroup_entry_t       *age = agg->agg_group;
 
206
                Modification            mod;
 
207
                const char              *text = NULL;
 
208
                char                    textbuf[1024];
 
209
                struct berval           vals[ 2 ], nvals[ 2 ];
 
210
 
 
211
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_cb <%s>\n",
 
212
                        rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
 
213
 
 
214
                vals[ 0 ] = rs->sr_entry->e_name;
 
215
                BER_BVZERO( &vals[ 1 ] );
 
216
                nvals[ 0 ] = rs->sr_entry->e_nname;
 
217
                BER_BVZERO( &nvals[ 1 ] );
 
218
 
 
219
                mod.sm_op = LDAP_MOD_ADD;
 
220
                mod.sm_desc = age->age_def->agd_member_ad;
 
221
                mod.sm_type = age->age_def->agd_member_ad->ad_cname;
 
222
                mod.sm_values = vals;
 
223
                mod.sm_nvalues = nvals;
 
224
                mod.sm_numvals = 1;
 
225
 
 
226
                modify_add_values( agg->agg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
 
227
        }
 
228
 
 
229
        return 0;
 
230
}
 
231
 
 
232
/* 
 
233
** Callback used to add entries to a group, which is already in the database.
 
234
** (used in on_response)
 
235
** The group is passed in autogroup_ga_t->agg_group
 
236
** NOTE: Very slow.
 
237
*/
 
238
static int
 
239
autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
 
240
{
 
241
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
242
 
 
243
        assert( op->o_tag == LDAP_REQ_SEARCH );
 
244
 
 
245
        if ( rs->sr_type == REP_SEARCH ) {
 
246
                autogroup_ga_t          *agg = (autogroup_ga_t *)op->o_callback->sc_private;
 
247
                autogroup_entry_t       *age = agg->agg_group;
 
248
                Operation               o = *op;
 
249
                Modifications           *modlist;
 
250
                SlapReply               sreply = {REP_RESULT};
 
251
                const char              *text = NULL;
 
252
                char                    textbuf[1024];
 
253
                struct berval           vals[ 2 ], nvals[ 2 ];
 
254
                slap_callback           cb = { NULL, slap_null_cb, NULL, NULL };
 
255
 
 
256
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_modify_cb <%s>\n",
 
257
                        rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
 
258
 
 
259
                vals[ 0 ] = rs->sr_entry->e_name;
 
260
                BER_BVZERO( &vals[ 1 ] );
 
261
                nvals[ 0 ] = rs->sr_entry->e_nname;
 
262
                BER_BVZERO( &nvals[ 1 ] );
 
263
 
 
264
                modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
 
265
 
 
266
                modlist->sml_op = LDAP_MOD_ADD;
 
267
                modlist->sml_desc = age->age_def->agd_member_ad;
 
268
                modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
 
269
 
 
270
                ber_bvarray_dup_x( &modlist->sml_values, vals, NULL );
 
271
                ber_bvarray_dup_x( &modlist->sml_nvalues, nvals, NULL );
 
272
                modlist->sml_numvals = 1;
 
273
 
 
274
                modlist->sml_flags = SLAP_MOD_INTERNAL;
 
275
                modlist->sml_next = NULL;
 
276
 
 
277
                if ( agg->agg_mod == NULL ) {
 
278
                        agg->agg_mod = modlist;
 
279
                        agg->agg_mod_last = modlist;
 
280
                } else {
 
281
                        agg->agg_mod_last->sml_next = modlist;
 
282
                        agg->agg_mod_last = modlist;
 
283
                }
 
284
 
 
285
        }
 
286
 
 
287
        return 0;
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
** Adds all entries matching the passed filter to the specified group.
 
293
** If modify == 1, then we modify the group's entry in the database using be_modify.
 
294
** If modify == 0, then, we must supply a rw entry for the group, 
 
295
**      because we only modify the entry, without calling be_modify.
 
296
** e    - the group entry, to which the members will be added
 
297
** age  - the group
 
298
** agf  - the filter
 
299
*/
 
300
static int
 
301
autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *age, autogroup_filter_t *agf, int modify)
 
302
{
 
303
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
304
        Operation               o = *op;
 
305
        SlapReply               rs = { REP_SEARCH };
 
306
        slap_callback           cb = { 0 };
 
307
        slap_callback           null_cb = { NULL, slap_null_cb, NULL, NULL };
 
308
        autogroup_ga_t          agg;
 
309
 
 
310
        Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n",
 
311
                age->age_dn.bv_val, 0, 0);
 
312
 
 
313
        o.ors_attrsonly = 0;
 
314
        o.o_tag = LDAP_REQ_SEARCH;
 
315
 
 
316
        o.o_req_dn = agf->agf_dn;
 
317
        o.o_req_ndn = agf->agf_ndn;
 
318
 
 
319
        o.ors_filterstr = agf->agf_filterstr;
 
320
        o.ors_filter = agf->agf_filter;
 
321
 
 
322
        o.ors_scope = agf->agf_scope;
 
323
        o.ors_deref = LDAP_DEREF_NEVER;
 
324
        o.ors_limit = NULL;
 
325
        o.ors_tlimit = SLAP_NO_LIMIT;
 
326
        o.ors_slimit = SLAP_NO_LIMIT;
 
327
        o.ors_attrs =  slap_anlist_no_attrs;
 
328
 
 
329
        agg.agg_group = age;
 
330
        agg.agg_mod = NULL;
 
331
        agg.agg_mod_last = NULL;
 
332
        agg.agg_entry = e;
 
333
        cb.sc_private = &agg;
 
334
 
 
335
        if ( modify == 1 ) {
 
336
                cb.sc_response = autogroup_member_search_modify_cb;
 
337
        } else {
 
338
                cb.sc_response = autogroup_member_search_cb;
 
339
        }
 
340
 
 
341
        cb.sc_cleanup = NULL;
 
342
        cb.sc_next = NULL;
 
343
 
 
344
        o.o_callback = &cb;
 
345
 
 
346
        o.o_bd->bd_info = (BackendInfo *)on->on_info;
 
347
        op->o_bd->be_search( &o, &rs );
 
348
        o.o_bd->bd_info = (BackendInfo *)on;    
 
349
 
 
350
        if ( modify == 1 ) {
 
351
                o = *op;
 
352
                o.o_callback = &null_cb;
 
353
                o.o_tag = LDAP_REQ_MODIFY;
 
354
                o.orm_modlist = agg.agg_mod;
 
355
                o.o_req_dn = age->age_dn;
 
356
                o.o_req_ndn = age->age_ndn;
 
357
                o.o_relax = SLAP_CONTROL_CRITICAL;
 
358
                o.o_managedsait = SLAP_CONTROL_NONCRITICAL;
 
359
                o.o_permissive_modify = 1;
 
360
 
 
361
                o.o_bd->bd_info = (BackendInfo *)on->on_info;
 
362
                (void)op->o_bd->be_modify( &o, &rs );
 
363
                o.o_bd->bd_info = (BackendInfo *)on;    
 
364
 
 
365
                slap_mods_free(agg.agg_mod, 1);
 
366
        }
 
367
 
 
368
        return 0;
 
369
}
 
370
 
 
371
/* 
 
372
** Adds a group to the internal list from the passed entry.
 
373
** scan specifies whether to add all maching members to the group.
 
374
** modify specifies whether to modify the given group entry (when modify == 0),
 
375
**      or to modify the group entry in the database (when modify == 1 and e = NULL and ndn != NULL).
 
376
** agi  - pointer to the groups and the attribute definitions
 
377
** agd - the attribute definition of the added group
 
378
** e    - the entry representing the group, can be NULL if the ndn is specified, and modify == 1
 
379
** ndn  - the DN of the group, can be NULL if we give a non-NULL e
 
380
*/
 
381
static int
 
382
autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd, Entry *e, BerValue *ndn, int scan, int modify)
 
383
{
 
384
        autogroup_entry_t       **agep = &agi->agi_entry;
 
385
        autogroup_filter_t      *agf, *agf_prev = NULL;
 
386
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
387
        LDAPURLDesc             *lud = NULL;
 
388
        Attribute               *a;
 
389
        BerValue                *bv, dn;
 
390
        int                     rc = 0, match = 1, null_entry = 0;
 
391
 
 
392
        if ( e == NULL ) {
 
393
                if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) !=
 
394
                        LDAP_SUCCESS || e == NULL ) {
 
395
                        Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot get entry for <%s>\n", ndn->bv_val, 0, 0);
 
396
                        return 1;
 
397
                }
 
398
 
 
399
                null_entry = 1;
 
400
        }
 
401
 
 
402
        Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_group <%s>\n",
 
403
                e->e_name.bv_val, 0, 0);
 
404
 
 
405
        if ( agi->agi_entry != NULL ) {
 
406
                for ( ; *agep ; agep = &(*agep)->age_next ) {
 
407
                        dnMatch( &match, 0, NULL, NULL, &e->e_nname, &(*agep)->age_ndn );
 
408
                        if ( match == 0 ) {
 
409
                                Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0);
 
410
                                return 1;
 
411
                        }
 
412
                        /* goto last */;
 
413
                }
 
414
        }
 
415
 
 
416
 
 
417
        *agep = (autogroup_entry_t *)ch_calloc( 1, sizeof( autogroup_entry_t ) );
 
418
        ldap_pvt_thread_mutex_init( &(*agep)->age_mutex );
 
419
        (*agep)->age_def = agd;
 
420
        (*agep)->age_filter = NULL;
 
421
 
 
422
        ber_dupbv( &(*agep)->age_dn, &e->e_name );
 
423
        ber_dupbv( &(*agep)->age_ndn, &e->e_nname );
 
424
 
 
425
        a = attrs_find( e->e_attrs, agd->agd_member_url_ad );
 
426
 
 
427
        if ( null_entry == 1 ) {
 
428
                a = attrs_dup( a );
 
429
                overlay_entry_release_ov( op, e, 0, on );
 
430
        }
 
431
 
 
432
        if( a == NULL ) {
 
433
                Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group has no memberURL\n", 0,0,0);
 
434
        } else {
 
435
                for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
 
436
 
 
437
                        agf = (autogroup_filter_t*)ch_calloc( 1, sizeof( autogroup_filter_t ) );
 
438
 
 
439
                        if ( ldap_url_parse( bv->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
 
440
                                Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot parse url <%s>\n", bv->bv_val,0,0);
 
441
                                /* FIXME: error? */
 
442
                                ch_free( agf ); 
 
443
                                continue;
 
444
                        }
 
445
 
 
446
                        agf->agf_scope = lud->lud_scope;
 
447
 
 
448
                        if ( lud->lud_dn == NULL ) {
 
449
                                BER_BVSTR( &dn, "" );
 
450
                        } else {
 
451
                                ber_str2bv( lud->lud_dn, 0, 0, &dn );
 
452
                        }
 
453
 
 
454
                        rc = dnPrettyNormal( NULL, &dn, &agf->agf_dn, &agf->agf_ndn, NULL );
 
455
                        if ( rc != LDAP_SUCCESS ) {
 
456
                                Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot normalize DN <%s>\n", dn.bv_val,0,0);
 
457
                                /* FIXME: error? */
 
458
                                goto cleanup;
 
459
                        }
 
460
 
 
461
                        if ( lud->lud_filter != NULL ) {
 
462
                                ber_str2bv( lud->lud_filter, 0, 1, &agf->agf_filterstr);
 
463
                                agf->agf_filter = str2filter( lud->lud_filter );
 
464
                        }                       
 
465
 
 
466
                        agf->agf_next = NULL;
 
467
 
 
468
 
 
469
                        if( (*agep)->age_filter == NULL ) {
 
470
                                (*agep)->age_filter = agf;
 
471
                        }
 
472
 
 
473
                        if( agf_prev != NULL ) {
 
474
                                agf_prev->agf_next = agf;
 
475
                        }
 
476
 
 
477
                        agf_prev = agf;
 
478
 
 
479
                        if ( scan == 1 ){
 
480
                                autogroup_add_members_from_filter( op, e, (*agep), agf, modify );
 
481
                        }
 
482
 
 
483
                        Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: added memberURL DN <%s> with filter <%s>\n",
 
484
                                agf->agf_ndn.bv_val, agf->agf_filterstr.bv_val, 0);
 
485
 
 
486
                        ldap_free_urldesc( lud );
 
487
 
 
488
                        continue;
 
489
 
 
490
 
 
491
cleanup:;
 
492
 
 
493
                        ldap_free_urldesc( lud );                               
 
494
                        ch_free( agf ); 
 
495
                }
 
496
        }
 
497
 
 
498
        if ( null_entry == 1 ) {
 
499
                attrs_free( a );
 
500
        }
 
501
        return rc;
 
502
}
 
503
 
 
504
/* 
 
505
** Used when opening the database to add all existing 
 
506
** groups from the database to our internal list.
 
507
*/
 
508
static int
 
509
autogroup_group_add_cb( Operation *op, SlapReply *rs )
 
510
{
 
511
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
512
 
 
513
        assert( op->o_tag == LDAP_REQ_SEARCH );
 
514
 
 
515
 
 
516
        if ( rs->sr_type == REP_SEARCH ) {
 
517
                autogroup_sc_t          *ags = (autogroup_sc_t *)op->o_callback->sc_private;
 
518
 
 
519
                Debug(LDAP_DEBUG_TRACE, "==> autogroup_group_add_cb <%s>\n",
 
520
                        rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
 
521
 
 
522
                autogroup_add_group( op, ags->ags_info, ags->ags_def, rs->sr_entry, NULL, 0, 0);
 
523
        }
 
524
 
 
525
        return 0;
 
526
}
 
527
 
 
528
 
 
529
/*
 
530
** When adding a group, we first strip any existing members,
 
531
** and add all which match the filters ourselfs.
 
532
*/
 
533
static int
 
534
autogroup_add_entry( Operation *op, SlapReply *rs)
 
535
{
 
536
                slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
537
        autogroup_info_t                *agi = (autogroup_info_t *)on->on_bi.bi_private;
 
538
        autogroup_def_t         *agd = agi->agi_def;
 
539
        autogroup_entry_t       *age = agi->agi_entry;
 
540
        autogroup_filter_t      *agf;
 
541
        Attribute               *a;
 
542
        int                     rc = 0;
 
543
 
 
544
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n", 
 
545
                op->ora_e->e_name.bv_val, 0, 0);
 
546
 
 
547
        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );          
 
548
 
 
549
        /* Check if it's a group. */
 
550
        for ( ; agd ; agd = agd->agd_next ) {
 
551
                if ( is_entry_objectclass_or_sub( op->ora_e, agd->agd_oc ) ) {
 
552
                        Modification            mod;
 
553
                        const char              *text = NULL;
 
554
                        char                    textbuf[1024];
 
555
 
 
556
                        mod.sm_op = LDAP_MOD_DELETE;
 
557
                        mod.sm_desc = agd->agd_member_ad;
 
558
                        mod.sm_type = agd->agd_member_ad->ad_cname;
 
559
                        mod.sm_values = NULL;
 
560
                        mod.sm_nvalues = NULL;
 
561
 
 
562
                        /* We don't want any member attributes added by the user. */
 
563
                        modify_delete_values( op->ora_e, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
 
564
 
 
565
                        autogroup_add_group( op, agi, agd, op->ora_e, NULL, 1 , 0);
 
566
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
567
                        return SLAP_CB_CONTINUE;
 
568
                }
 
569
        }
 
570
 
 
571
        for ( ; age ; age = age->age_next ) {
 
572
                ldap_pvt_thread_mutex_lock( &age->age_mutex );          
 
573
 
 
574
                /* Check if any of the filters are the suffix to the entry DN. 
 
575
                   If yes, we can test that filter against the entry. */
 
576
 
 
577
                for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
 
578
                        if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
 
579
                                rc = test_filter( op, op->ora_e, agf->agf_filter );
 
580
                                if ( rc == LDAP_COMPARE_TRUE ) {
 
581
                                autogroup_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, age );
 
582
                                        break;
 
583
                                }
 
584
                        }
 
585
                }
 
586
                ldap_pvt_thread_mutex_unlock( &age->age_mutex );                
 
587
        }
 
588
 
 
589
        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
590
 
 
591
        return SLAP_CB_CONTINUE;
 
592
}
 
593
 
 
594
/*
 
595
** agi  - internal group and attribute definitions list
 
596
** e    - the group to remove from the internal list
 
597
*/
 
598
static int
 
599
autogroup_delete_group( autogroup_info_t *agi, autogroup_entry_t *e )
 
600
{
 
601
        autogroup_entry_t       *age = agi->agi_entry,
 
602
                                *age_prev = NULL,
 
603
                                *age_next;
 
604
        int                     rc = 1;
 
605
 
 
606
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_group <%s>\n", 
 
607
                age->age_dn.bv_val, 0, 0);
 
608
 
 
609
        for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
 
610
                age_next = age->age_next;
 
611
 
 
612
                if ( age == e ) {
 
613
                        autogroup_filter_t      *agf = age->age_filter,
 
614
                                                        *agf_next;
 
615
 
 
616
                        if ( age_prev != NULL ) {
 
617
                                age_prev->age_next = age_next;
 
618
                        } else {
 
619
                                agi->agi_entry = NULL;
 
620
                        }
 
621
 
 
622
                        ch_free( age->age_dn.bv_val );
 
623
                        ch_free( age->age_ndn.bv_val );
 
624
 
 
625
                        for( agf_next = agf ; agf_next ; agf = agf_next ){
 
626
                                agf_next = agf->agf_next;
 
627
 
 
628
                                filter_free( agf->agf_filter );
 
629
                                ch_free( agf->agf_filterstr.bv_val );
 
630
                                ch_free( agf->agf_dn.bv_val );
 
631
                                ch_free( agf->agf_ndn.bv_val );
 
632
                        }
 
633
 
 
634
                        ldap_pvt_thread_mutex_unlock( &age->age_mutex );                
 
635
                        ldap_pvt_thread_mutex_destroy( &age->age_mutex );
 
636
                        ch_free( age );
 
637
 
 
638
                        rc = 0; 
 
639
                        return rc;
 
640
 
 
641
                }
 
642
        }
 
643
 
 
644
        Debug( LDAP_DEBUG_TRACE, "autogroup_delete_group: group <%s> not found, should not happen\n", age->age_dn.bv_val, 0, 0);
 
645
 
 
646
        return rc;
 
647
 
 
648
}
 
649
 
 
650
static int
 
651
autogroup_delete_entry( Operation *op, SlapReply *rs)
 
652
{
 
653
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
654
        autogroup_info_t                *agi = (autogroup_info_t *)on->on_bi.bi_private;
 
655
        autogroup_def_t         *agd = agi->agi_def;
 
656
        autogroup_entry_t       *age = agi->agi_entry,
 
657
                                *age_prev, *age_next;
 
658
        autogroup_filter_t      *agf;
 
659
        Entry                   *e;
 
660
        int                     matched_group = 0, rc = 0;
 
661
 
 
662
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
663
 
 
664
        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
 
665
 
 
666
        if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
 
667
                LDAP_SUCCESS || e == NULL ) {
 
668
                Debug( LDAP_DEBUG_TRACE, "autogroup_delete_entry: cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
669
                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                        
 
670
                return SLAP_CB_CONTINUE;
 
671
        }
 
672
 
 
673
        /* Check if the entry to be deleted is one of our groups. */
 
674
        for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
 
675
                ldap_pvt_thread_mutex_lock( &age->age_mutex );
 
676
                age_next = age->age_next;
 
677
 
 
678
                if ( is_entry_objectclass_or_sub( e, age->age_def->agd_oc ) ) {
 
679
                        int match = 1;
 
680
 
 
681
                        matched_group = 1;
 
682
 
 
683
                        dnMatch( &match, 0, NULL, NULL, &e->e_nname, &age->age_ndn );
 
684
 
 
685
                        if ( match == 0 ) {
 
686
                                autogroup_filter_t      *agf = age->age_filter,
 
687
                                                        *agf_next;
 
688
 
 
689
                                autogroup_delete_group( agi, age );
 
690
                                break;
 
691
                        }
 
692
                }
 
693
 
 
694
                ldap_pvt_thread_mutex_unlock( &age->age_mutex );                        
 
695
        }
 
696
 
 
697
        if ( matched_group == 1 ) {
 
698
                overlay_entry_release_ov( op, e, 0, on );
 
699
                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
700
                return SLAP_CB_CONTINUE;
 
701
        }
 
702
 
 
703
        /* Check if the entry matches any of the groups.
 
704
           If yes, we can delete the entry from that group. */
 
705
 
 
706
        for ( age = agi->agi_entry ; age ; age = age->age_next ) {
 
707
                ldap_pvt_thread_mutex_lock( &age->age_mutex );          
 
708
 
 
709
                for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
 
710
                        if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
 
711
                                rc = test_filter( op, e, agf->agf_filter );
 
712
                                if ( rc == LDAP_COMPARE_TRUE ) {
 
713
                                autogroup_delete_member_from_group( op, &e->e_name, &e->e_nname, age );
 
714
                                        break;
 
715
                                }
 
716
                        }
 
717
                }
 
718
                ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
719
        }
 
720
 
 
721
        overlay_entry_release_ov( op, e, 0, on );
 
722
        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
723
 
 
724
        return SLAP_CB_CONTINUE;
 
725
}
 
726
 
 
727
static int
 
728
autogroup_response( Operation *op, SlapReply *rs )
 
729
{
 
730
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
731
        autogroup_info_t                *agi = (autogroup_info_t *)on->on_bi.bi_private;
 
732
        autogroup_def_t         *agd = agi->agi_def;
 
733
        autogroup_entry_t       *age = agi->agi_entry;
 
734
        autogroup_filter_t      *agf;
 
735
        BerValue                new_dn, new_ndn, pdn;
 
736
        Entry                   *e, *group;
 
737
        Attribute               *a;
 
738
        int                     is_olddn, is_newdn, dn_equal;
 
739
 
 
740
        if ( op->o_tag == LDAP_REQ_MODRDN ) {
 
741
                if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
 
742
 
 
743
                        Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
744
 
 
745
                        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );                  
 
746
 
 
747
                        if ( op->oq_modrdn.rs_newSup ) {
 
748
                                pdn = *op->oq_modrdn.rs_newSup;
 
749
                        } else {
 
750
                                dnParent( &op->o_req_dn, &pdn );
 
751
                        }
 
752
                        build_new_dn( &new_dn, &pdn, &op->orr_newrdn, op->o_tmpmemctx );
 
753
 
 
754
                        if ( op->oq_modrdn.rs_nnewSup ) {
 
755
                                pdn = *op->oq_modrdn.rs_nnewSup;
 
756
                        } else {
 
757
                                dnParent( &op->o_req_ndn, &pdn );
 
758
                        }
 
759
                        build_new_dn( &new_ndn, &pdn, &op->orr_nnewrdn, op->o_tmpmemctx );
 
760
 
 
761
                        Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN to <%s>\n", new_dn.bv_val, 0, 0);
 
762
 
 
763
                        dnMatch( &dn_equal, 0, NULL, NULL, &op->o_req_ndn, &new_ndn );
 
764
 
 
765
                        if ( overlay_entry_get_ov( op, &new_ndn, NULL, NULL, 0, &e, on ) !=
 
766
                                LDAP_SUCCESS || e == NULL ) {
 
767
                                Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get entry for <%s>\n", new_dn.bv_val, 0, 0);
 
768
                                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
769
                                return SLAP_CB_CONTINUE;
 
770
                        }
 
771
 
 
772
                        a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
 
773
 
 
774
 
 
775
                        if ( a == NULL ) {
 
776
                                Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN entry <%s> has no objectClass\n", new_dn.bv_val, 0, 0);
 
777
                                overlay_entry_release_ov( op, e, 0, on );
 
778
                                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
779
                                return SLAP_CB_CONTINUE;
 
780
                        }
 
781
 
 
782
 
 
783
                        /* If a groups DN is modified, just update age_dn/ndn of that group with the new DN. */
 
784
                        for ( ; agd; agd = agd->agd_next ) {
 
785
 
 
786
                                if ( value_find_ex( slap_schema.si_ad_objectClass,
 
787
                                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
 
788
                                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
 
789
                                                a->a_nvals, &agd->agd_oc->soc_cname,
 
790
                                                op->o_tmpmemctx ) == 0 )
 
791
                                {               
 
792
                                        for ( age = agi->agi_entry ; age ; age = age->age_next ) {
 
793
                                                int match = 1;
 
794
 
 
795
                                                dnMatch( &match, 0, NULL, NULL, &age->age_ndn, &op->o_req_ndn );
 
796
                                                if ( match == 0 ) {
 
797
                                                        Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN updating group's DN to <%s>\n", new_dn.bv_val, 0, 0);
 
798
                                                        ber_dupbv( &age->age_dn, &new_dn );
 
799
                                                        ber_dupbv( &age->age_ndn, &new_ndn );
 
800
 
 
801
                                                        op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx  );
 
802
                                                        op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
 
803
                                                        overlay_entry_release_ov( op, e, 0, on );
 
804
                                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
805
                                                        return SLAP_CB_CONTINUE;
 
806
                                                }
 
807
                                        }
 
808
 
 
809
                                }
 
810
                        }
 
811
 
 
812
                        overlay_entry_release_ov( op, e, 0, on );
 
813
 
 
814
                        /* For each group: 
 
815
                           1. check if the orginal entry's DN is in the group.
 
816
                           2. chceck if the any of the group filter's base DN is a suffix of the new DN 
 
817
 
 
818
                           If 1 and 2 are both false, we do nothing.
 
819
                           If 1 and 2 is true, we remove the old DN from the group, and add the new DN.
 
820
                           If 1 is false, and 2 is true, we check the entry against the group's filters,
 
821
                                and add it's DN to the group.
 
822
                           If 1 is true, and 2 is false, we delete the entry's DN from the group.
 
823
                        */
 
824
                        for ( age = agi->agi_entry ; age ; age = age->age_next ) {
 
825
                                is_olddn = 0;
 
826
                                is_newdn = 0;
 
827
 
 
828
 
 
829
                                ldap_pvt_thread_mutex_lock( &age->age_mutex );
 
830
 
 
831
                                if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
 
832
                                        LDAP_SUCCESS || group == NULL ) {
 
833
                                        Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get group entry <%s>\n", age->age_dn.bv_val, 0, 0);
 
834
 
 
835
                                        op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
 
836
                                        op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
 
837
 
 
838
                                        ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
839
                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
840
                                        return SLAP_CB_CONTINUE;
 
841
                                }
 
842
 
 
843
                                a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
 
844
 
 
845
                                if ( a != NULL ) {
 
846
                                        if ( value_find_ex( age->age_def->agd_member_ad,
 
847
                                                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
 
848
                                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
 
849
                                                        a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 ) 
 
850
                                        {
 
851
                                                is_olddn = 1;
 
852
                                        }
 
853
 
 
854
                                }
 
855
 
 
856
                                overlay_entry_release_ov( op, group, 0, on );
 
857
 
 
858
                                for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
 
859
                                        if ( dnIsSuffix( &new_ndn, &agf->agf_ndn ) ) {
 
860
                                                is_newdn = 1;
 
861
                                                break;
 
862
                                        }
 
863
                                }
 
864
 
 
865
 
 
866
                                if ( is_olddn == 1 && is_newdn == 0 ) {
 
867
                                        autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
 
868
                                } else
 
869
                                if ( is_olddn == 0 && is_newdn == 1 ) {
 
870
                                        for ( agf = age->age_filter; agf; agf = agf->agf_next ) {
 
871
                                                if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
 
872
                                                        autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
 
873
                                                        break;
 
874
                                                }
 
875
                                        }
 
876
                                } else
 
877
                                if ( is_olddn == 1 && is_newdn == 1 && dn_equal != 0 ) {
 
878
                                        autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
 
879
                                        autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
 
880
                                }
 
881
 
 
882
                                ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
883
                        }
 
884
 
 
885
                        op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
 
886
                        op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
 
887
 
 
888
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                        
 
889
                }
 
890
        }
 
891
 
 
892
        if ( op->o_tag == LDAP_REQ_MODIFY ) {
 
893
                if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS  && !get_manageDSAit( op ) ) {
 
894
                        Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODIFY <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
895
 
 
896
                        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );                  
 
897
 
 
898
                        if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
 
899
                                LDAP_SUCCESS || e == NULL ) {
 
900
                                Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
901
                                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
902
                                return SLAP_CB_CONTINUE;
 
903
                        }
 
904
 
 
905
                        a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
 
906
 
 
907
 
 
908
                        if ( a == NULL ) {
 
909
                                Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
 
910
                                overlay_entry_release_ov( op, e, 0, on );
 
911
                                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
912
                                return SLAP_CB_CONTINUE;
 
913
                        }
 
914
 
 
915
 
 
916
                        /* If we modify a group's memberURL, we have to delete all of it's members,
 
917
                           and add them anew, because we cannot tell from which memberURL a member was added. */
 
918
                        for ( ; agd; agd = agd->agd_next ) {
 
919
 
 
920
                                if ( value_find_ex( slap_schema.si_ad_objectClass,
 
921
                                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
 
922
                                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
 
923
                                                a->a_nvals, &agd->agd_oc->soc_cname,
 
924
                                                op->o_tmpmemctx ) == 0 )
 
925
                                {
 
926
                                        Modifications   *m;
 
927
                                        int             match = 1;
 
928
 
 
929
                                        m = op->orm_modlist;
 
930
 
 
931
                                        for ( ; age ; age = age->age_next ) {
 
932
                                                ldap_pvt_thread_mutex_lock( &age->age_mutex );
 
933
 
 
934
                                                dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
 
935
 
 
936
                                                if ( match == 0 ) {
 
937
                                                        for ( ; m ; m = m->sml_next ) {
 
938
                                                                if ( m->sml_desc == age->age_def->agd_member_url_ad ) {
 
939
                                                                        autogroup_def_t *group_agd = age->age_def;
 
940
                                                                        Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY changing memberURL for group <%s>\n", 
 
941
                                                                                op->o_req_dn.bv_val, 0, 0);
 
942
 
 
943
                                                                        overlay_entry_release_ov( op, e, 0, on );
 
944
 
 
945
                                                                        autogroup_delete_member_from_group( op, NULL, NULL, age );
 
946
                                                                        autogroup_delete_group( agi, age );
 
947
 
 
948
                                                                        autogroup_add_group( op, agi, group_agd, NULL, &op->o_req_ndn, 1, 1);
 
949
 
 
950
                                                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
951
                                                                        return SLAP_CB_CONTINUE;
 
952
                                                                }
 
953
                                                        }
 
954
 
 
955
                                                        ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
956
                                                        break;
 
957
                                                }
 
958
 
 
959
                                                ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
960
                                        }
 
961
 
 
962
                                        overlay_entry_release_ov( op, e, 0, on );
 
963
                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
964
                                        return SLAP_CB_CONTINUE;
 
965
                                }
 
966
                        }
 
967
 
 
968
                        overlay_entry_release_ov( op, e, 0, on );
 
969
 
 
970
                        /* When modifing any of the attributes of an entry, we must
 
971
                           check if the entry is in any of our groups, and if
 
972
                           the modified entry maches any of the filters of that group.
 
973
 
 
974
                           If the entry exists in a group, but the modified attributes do
 
975
                                not match any of the group's filters, we delete the entry from that group.
 
976
                           If the entry doesn't exist in a group, but matches a filter, 
 
977
                                we add it to that group.
 
978
                        */
 
979
                        for ( age = agi->agi_entry ; age ; age = age->age_next ) {
 
980
                                is_olddn = 0;
 
981
                                is_newdn = 0;
 
982
 
 
983
 
 
984
                                ldap_pvt_thread_mutex_lock( &age->age_mutex );
 
985
 
 
986
                                if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
 
987
                                        LDAP_SUCCESS || group == NULL ) {
 
988
                                        Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n", 
 
989
                                                age->age_dn.bv_val, 0, 0);
 
990
 
 
991
                                        ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
992
                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
993
                                        return SLAP_CB_CONTINUE;
 
994
                                }
 
995
 
 
996
                                a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
 
997
 
 
998
                                if ( a != NULL ) {
 
999
                                        if ( value_find_ex( age->age_def->agd_member_ad,
 
1000
                                                        SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
 
1001
                                                        SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
 
1002
                                                        a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 ) 
 
1003
                                        {
 
1004
                                                is_olddn = 1;
 
1005
                                        }
 
1006
 
 
1007
                                }
 
1008
 
 
1009
                                overlay_entry_release_ov( op, group, 0, on );
 
1010
 
 
1011
                                for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
 
1012
                                        if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
 
1013
                                                if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
 
1014
                                                        is_newdn = 1;
 
1015
                                                        break;
 
1016
                                                }
 
1017
                                        }
 
1018
                                }
 
1019
 
 
1020
                                if ( is_olddn == 1 && is_newdn == 0 ) {
 
1021
                                        autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
 
1022
                                } else
 
1023
                                if ( is_olddn == 0 && is_newdn == 1 ) {
 
1024
                                        autogroup_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, age );
 
1025
                                } 
 
1026
 
 
1027
                                ldap_pvt_thread_mutex_unlock( &age->age_mutex );
 
1028
                        }
 
1029
 
 
1030
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1031
                }
 
1032
        }
 
1033
 
 
1034
        return SLAP_CB_CONTINUE;
 
1035
}
 
1036
 
 
1037
/*
 
1038
** When modifing a group, we must deny any modifications to the member attribute,
 
1039
** because the group would be inconsistent.
 
1040
*/
 
1041
static int
 
1042
autogroup_modify_entry( Operation *op, SlapReply *rs)
 
1043
{
 
1044
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
 
1045
        autogroup_info_t                *agi = (autogroup_info_t *)on->on_bi.bi_private;
 
1046
        autogroup_def_t         *agd = agi->agi_def;
 
1047
        autogroup_entry_t       *age = agi->agi_entry;
 
1048
        Entry                   *e;
 
1049
        Attribute               *a;
 
1050
 
 
1051
        if ( get_manageDSAit( op ) ) {
 
1052
                return SLAP_CB_CONTINUE;
 
1053
        }
 
1054
 
 
1055
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_modify_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
1056
        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );                  
 
1057
 
 
1058
        if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
 
1059
                LDAP_SUCCESS || e == NULL ) {
 
1060
                Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
 
1061
                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1062
                return SLAP_CB_CONTINUE;
 
1063
        }
 
1064
 
 
1065
        a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
 
1066
 
 
1067
        if ( a == NULL ) {
 
1068
                Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
 
1069
                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
1070
                return SLAP_CB_CONTINUE;
 
1071
        }
 
1072
 
 
1073
 
 
1074
        for ( ; agd; agd = agd->agd_next ) {
 
1075
 
 
1076
                if ( value_find_ex( slap_schema.si_ad_objectClass,
 
1077
                                SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
 
1078
                                SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
 
1079
                                a->a_nvals, &agd->agd_oc->soc_cname,
 
1080
                                op->o_tmpmemctx ) == 0 )
 
1081
                {
 
1082
                        Modifications   *m;
 
1083
                        int             match = 1;
 
1084
 
 
1085
                        m = op->orm_modlist;
 
1086
 
 
1087
                        for ( ; age ; age = age->age_next ) {
 
1088
                                dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
 
1089
 
 
1090
                                if ( match == 0 ) {
 
1091
                                        for ( ; m ; m = m->sml_next ) {
 
1092
                                                if ( m->sml_desc == age->age_def->agd_member_ad ) {
 
1093
                                                        overlay_entry_release_ov( op, e, 0, on );
 
1094
                                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1095
                                                        Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry attempted to modify group's <%s> member attribute\n", op->o_req_dn.bv_val, 0, 0);
 
1096
                                                        send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to modify dynamic group member attribute");
 
1097
                                                        return LDAP_CONSTRAINT_VIOLATION;
 
1098
                                                }
 
1099
                                        }
 
1100
                                        break;
 
1101
                                }
 
1102
                        }
 
1103
 
 
1104
                        overlay_entry_release_ov( op, e, 0, on );
 
1105
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1106
                        return SLAP_CB_CONTINUE;
 
1107
                }
 
1108
        }
 
1109
 
 
1110
        overlay_entry_release_ov( op, e, 0, on );
 
1111
        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                        
 
1112
        return SLAP_CB_CONTINUE;
 
1113
}
 
1114
 
 
1115
/* 
 
1116
** Builds a filter for searching for the 
 
1117
** group entries, according to the objectClass. 
 
1118
*/
 
1119
static int
 
1120
autogroup_build_def_filter( autogroup_def_t *agd, Operation *op )
 
1121
{
 
1122
        char    *ptr;
 
1123
 
 
1124
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_build_def_filter\n", 0, 0, 0);
 
1125
 
 
1126
        op->ors_filterstr.bv_len = STRLENOF( "(=)" ) 
 
1127
                        + slap_schema.si_ad_objectClass->ad_cname.bv_len
 
1128
                        + agd->agd_oc->soc_cname.bv_len;
 
1129
        ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
 
1130
        *ptr++ = '(';
 
1131
        ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
 
1132
        *ptr++ = '=';
 
1133
        ptr = lutil_strcopy( ptr, agd->agd_oc->soc_cname.bv_val );
 
1134
        *ptr++ = ')';
 
1135
        *ptr = '\0';
 
1136
 
 
1137
        op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
 
1138
 
 
1139
        assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );
 
1140
 
 
1141
        return 0;
 
1142
}
 
1143
 
 
1144
enum {
 
1145
        AG_ATTRSET = 1,
 
1146
        AG_LAST
 
1147
};
 
1148
 
 
1149
static ConfigDriver     ag_cfgen;
 
1150
 
 
1151
static ConfigTable agcfg[] = {
 
1152
        { "autogroup-attrset", "group-oc> <URL-ad> <member-ad",
 
1153
                3, 4, 0, ARG_MAGIC|AG_ATTRSET, ag_cfgen,
 
1154
                "( OLcfgCtAt:2.1 NAME 'olcAGattrSet' "
 
1155
                        "DESC 'Automatic groups: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
 
1156
                        "EQUALITY caseIgnoreMatch "
 
1157
                        "SYNTAX OMsDirectoryString "
 
1158
                        "X-ORDERED 'VALUES' )",
 
1159
                        NULL, NULL },
 
1160
        { NULL, NULL, 0, 0, 0, ARG_IGNORED }
 
1161
};
 
1162
 
 
1163
static ConfigOCs agocs[] = {
 
1164
        { "( OLcfgCtOc:2.1 "
 
1165
                "NAME 'olcAutomaticGroups' "
 
1166
                "DESC 'Automatic groups configuration' "
 
1167
                "SUP olcOverlayConfig "
 
1168
                "MAY olcAGattrSet )",
 
1169
                Cft_Overlay, agcfg, NULL, NULL },
 
1170
        { NULL, 0, NULL }
 
1171
};
 
1172
 
 
1173
 
 
1174
static int
 
1175
ag_cfgen( ConfigArgs *c )
 
1176
{
 
1177
        slap_overinst           *on = (slap_overinst *)c->bi;
 
1178
        autogroup_info_t                *agi = (autogroup_info_t *)on->on_bi.bi_private;
 
1179
        autogroup_def_t         *agd;
 
1180
        autogroup_entry_t       *age;
 
1181
 
 
1182
        int rc = 0, i;
 
1183
 
 
1184
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_cfgen\n", 0, 0, 0);
 
1185
 
 
1186
        if( agi == NULL ) {
 
1187
                agi = (autogroup_info_t*)ch_calloc( 1, sizeof(autogroup_info_t) );
 
1188
                ldap_pvt_thread_mutex_init( &agi->agi_mutex );
 
1189
                agi->agi_def = NULL;
 
1190
                agi->agi_entry = NULL;
 
1191
                on->on_bi.bi_private = (void *)agi;
 
1192
        }
 
1193
 
 
1194
        agd = agi->agi_def;
 
1195
        age = agi->agi_entry;
 
1196
 
 
1197
        if ( c->op == SLAP_CONFIG_EMIT ) {
 
1198
 
 
1199
                ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
 
1200
 
 
1201
                for ( i = 0 ; agd ; i++, agd = agd->agd_next ) {
 
1202
                        struct berval   bv;
 
1203
                        char            *ptr = c->cr_msg;
 
1204
 
 
1205
                        assert(agd->agd_oc != NULL);
 
1206
                        assert(agd->agd_member_url_ad != NULL);
 
1207
                        assert(agd->agd_member_ad != NULL);
 
1208
 
 
1209
                        ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1210
                                SLAP_X_ORDERED_FMT "%s %s %s", i,
 
1211
                                agd->agd_oc->soc_cname.bv_val,
 
1212
                                agd->agd_member_url_ad->ad_cname.bv_val,
 
1213
                                agd->agd_member_ad->ad_cname.bv_val );
 
1214
 
 
1215
                        bv.bv_val = c->cr_msg;
 
1216
                        bv.bv_len = ptr - bv.bv_val;
 
1217
                        value_add_one ( &c->rvalue_vals, &bv );
 
1218
 
 
1219
                }
 
1220
                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1221
 
 
1222
                return rc;
 
1223
 
 
1224
        }else if ( c->op == LDAP_MOD_DELETE ) {
 
1225
                if ( c->valx < 0) {
 
1226
                        autogroup_def_t                 *agd_next;
 
1227
                        autogroup_entry_t       *age_next;
 
1228
                        autogroup_filter_t      *agf = age->age_filter,
 
1229
                                                *agf_next;
 
1230
 
 
1231
                        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
 
1232
 
 
1233
                        for ( agd_next = agd; agd_next; agd = agd_next ) {
 
1234
                                agd_next = agd->agd_next;
 
1235
 
 
1236
                                ch_free( agd );
 
1237
                        }
 
1238
 
 
1239
                        for ( age_next = age ; age_next ; age = age_next ) {
 
1240
                                age_next = age->age_next;
 
1241
 
 
1242
                                ch_free( age->age_dn.bv_val );
 
1243
                                ch_free( age->age_ndn.bv_val );
 
1244
 
 
1245
                                for( agf_next = agf ; agf_next ; agf = agf_next ){
 
1246
                                        agf_next = agf->agf_next;
 
1247
 
 
1248
                                        filter_free( agf->agf_filter );
 
1249
                                        ch_free( agf->agf_filterstr.bv_val );
 
1250
                                        ch_free( agf->agf_dn.bv_val );
 
1251
                                        ch_free( agf->agf_ndn.bv_val );
 
1252
                                }
 
1253
 
 
1254
                                ldap_pvt_thread_mutex_init( &age->age_mutex );
 
1255
                                ch_free( age );
 
1256
                        }
 
1257
 
 
1258
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1259
 
 
1260
                        ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
 
1261
                        ch_free( agi );
 
1262
                        on->on_bi.bi_private = NULL;
 
1263
 
 
1264
                } else {
 
1265
                        autogroup_def_t         **agdp;
 
1266
                        autogroup_entry_t       *age_next, *age_prev;
 
1267
                        autogroup_filter_t      *agf,
 
1268
                                                *agf_next;
 
1269
                        struct berval           *bv;
 
1270
 
 
1271
                        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
 
1272
 
 
1273
                        for ( i = 0, agdp = &agi->agi_def;
 
1274
                                i < c->valx; i++ ) 
 
1275
                        {
 
1276
                                if ( *agdp == NULL) {
 
1277
                                        return 1;
 
1278
                                }
 
1279
                                agdp = &(*agdp)->agd_next;
 
1280
                        }
 
1281
 
 
1282
                        agd = *agdp;
 
1283
                        *agdp = agd->agd_next;
 
1284
 
 
1285
                        for ( age_next = age , age_prev = NULL ; age_next ; age_prev = age, age = age_next ) {
 
1286
                                age_next = age->age_next;
 
1287
 
 
1288
                                if( age->age_def == agd ) {
 
1289
                                        agf = age->age_filter;
 
1290
 
 
1291
                                        ch_free( age->age_dn.bv_val );
 
1292
                                        ch_free( age->age_ndn.bv_val );
 
1293
 
 
1294
                                        for ( agf_next = agf; agf_next ; agf = agf_next ) {
 
1295
                                                agf_next = agf->agf_next;
 
1296
                                                filter_free( agf->agf_filter );
 
1297
                                                ch_free( agf->agf_filterstr.bv_val );
 
1298
                                                ch_free( agf->agf_dn.bv_val );
 
1299
                                                ch_free( agf->agf_ndn.bv_val );
 
1300
                                        }
 
1301
 
 
1302
                                        ldap_pvt_thread_mutex_destroy( &age->age_mutex );
 
1303
                                        ch_free( age );
 
1304
 
 
1305
                                        age = age_prev;
 
1306
 
 
1307
                                        if( age_prev != NULL ) {
 
1308
                                                age_prev->age_next = age_next;
 
1309
                                        }
 
1310
                                }
 
1311
                        }
 
1312
 
 
1313
                        ch_free( agd );
 
1314
                        agd = agi->agi_def;
 
1315
                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1316
 
 
1317
                }
 
1318
 
 
1319
                return rc;
 
1320
        }
 
1321
 
 
1322
        switch(c->type){
 
1323
        case AG_ATTRSET: {
 
1324
                autogroup_def_t         **agdp,
 
1325
                                        *agd_next = NULL;
 
1326
                ObjectClass             *oc = NULL;
 
1327
                AttributeDescription    *member_url_ad = NULL,
 
1328
                                        *member_ad = NULL;
 
1329
                const char              *text;
 
1330
 
 
1331
 
 
1332
                oc = oc_find( c->argv[ 1 ] );
 
1333
                if( oc == NULL ){
 
1334
                        snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1335
                                "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
 
1336
                                "unable to find ObjectClass \"%s\"",
 
1337
                                c->argv[ 1 ] );
 
1338
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
 
1339
                                c->log, c->cr_msg, 0 );
 
1340
                        return 1;
 
1341
                }
 
1342
 
 
1343
 
 
1344
                rc = slap_str2ad( c->argv[ 2 ], &member_url_ad, &text );
 
1345
                if( rc != LDAP_SUCCESS ) {
 
1346
                        snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1347
                                "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
 
1348
                                "unable to find AttributeDescription \"%s\"",
 
1349
                                c->argv[ 2 ] );
 
1350
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
 
1351
                                c->log, c->cr_msg, 0 );         
 
1352
                        return 1;
 
1353
                }
 
1354
 
 
1355
                if( !is_at_subtype( member_url_ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
 
1356
                        snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1357
                                "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
 
1358
                                "AttributeDescription \"%s\" ",
 
1359
                                "must be of a subtype \"labeledURI\"",
 
1360
                                c->argv[ 2 ] );
 
1361
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
 
1362
                                c->log, c->cr_msg, 0 );
 
1363
                        return 1;
 
1364
                }
 
1365
 
 
1366
                rc = slap_str2ad( c->argv[3], &member_ad, &text );
 
1367
                if( rc != LDAP_SUCCESS ) {
 
1368
                        snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1369
                                "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
 
1370
                                "unable to find AttributeDescription \"%s\"",
 
1371
                                c->argv[ 3 ] );
 
1372
                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
 
1373
                                c->log, c->cr_msg, 0 );
 
1374
                        return 1;
 
1375
                }
 
1376
 
 
1377
                ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
 
1378
 
 
1379
                for ( agdp = &agi->agi_def ; *agdp ; agdp = &(*agdp)->agd_next ) {
 
1380
                        /* The same URL attribute / member attribute pair
 
1381
                        * cannot be repeated */
 
1382
 
 
1383
                        if ( (*agdp)->agd_member_url_ad == member_url_ad && (*agdp)->agd_member_ad == member_ad ) {
 
1384
                                snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1385
                                        "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
 
1386
                                        "URL attributeDescription \"%s\" already mapped",
 
1387
                                        member_ad->ad_cname.bv_val );
 
1388
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
 
1389
                                        c->log, c->cr_msg, 0 );
 
1390
/*                              return 1; //warning*/
 
1391
                        }
 
1392
                }
 
1393
 
 
1394
                if ( c->valx > 0 ) {
 
1395
                        int     i;
 
1396
 
 
1397
                        for ( i = 0, agdp = &agi->agi_def ;
 
1398
                                i < c->valx; i++ )
 
1399
                        {
 
1400
                                if ( *agdp == NULL ) {
 
1401
                                        snprintf( c->cr_msg, sizeof( c->cr_msg ),
 
1402
                                                "\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
 
1403
                                                "invalid index {%d}",
 
1404
                                                c->valx );
 
1405
                                        Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
 
1406
                                                c->log, c->cr_msg, 0 );
 
1407
 
 
1408
                                        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );                
 
1409
                                        return 1;
 
1410
                                }
 
1411
                                agdp = &(*agdp)->agd_next;
 
1412
                        }
 
1413
                        agd_next = *agdp;
 
1414
 
 
1415
                } else {
 
1416
                        for ( agdp = &agi->agi_def; *agdp;
 
1417
                                agdp = &(*agdp)->agd_next )
 
1418
                                /* goto last */;
 
1419
                }
 
1420
 
 
1421
                *agdp = (autogroup_def_t *)ch_calloc( 1, sizeof(autogroup_info_t));
 
1422
 
 
1423
                (*agdp)->agd_oc = oc;
 
1424
                (*agdp)->agd_member_url_ad = member_url_ad;
 
1425
                (*agdp)->agd_member_ad = member_ad;
 
1426
                (*agdp)->agd_next = agd_next;
 
1427
 
 
1428
                ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1429
 
 
1430
                } break;
 
1431
 
 
1432
        default:
 
1433
                rc = 1;
 
1434
                break;
 
1435
        }
 
1436
 
 
1437
        return rc;
 
1438
}
 
1439
 
 
1440
/* 
 
1441
** Do a search for all the groups in the
 
1442
** database, and add them to out internal list.
 
1443
*/
 
1444
static int
 
1445
autogroup_db_open(
 
1446
        BackendDB       *be,
 
1447
        ConfigReply     *cr )
 
1448
{
 
1449
        slap_overinst                   *on = (slap_overinst *) be->bd_info,
 
1450
                                *on_bd;
 
1451
        autogroup_info_t                *agi = on->on_bi.bi_private;
 
1452
        autogroup_def_t         *agd;
 
1453
        autogroup_sc_t          ags;
 
1454
        Operation               *op;
 
1455
        SlapReply               rs = { REP_RESULT };
 
1456
        slap_callback           cb = { 0 };
 
1457
 
 
1458
        void                            *thrctx = ldap_pvt_thread_pool_context();
 
1459
        Connection                      conn = { 0 };
 
1460
        OperationBuffer         opbuf;
 
1461
        BerValue                bv;
 
1462
        char                    *ptr;
 
1463
        int                     rc = 0;
 
1464
 
 
1465
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_open\n", 0, 0, 0);
 
1466
 
 
1467
        connection_fake_init( &conn, &opbuf, thrctx );
 
1468
        op = &opbuf.ob_op;
 
1469
 
 
1470
        op->ors_attrsonly = 0;
 
1471
        op->o_tag = LDAP_REQ_SEARCH;
 
1472
        op->o_dn = be->be_rootdn;
 
1473
        op->o_ndn = be->be_rootndn;
 
1474
 
 
1475
        op->o_req_dn = be->be_suffix[0];
 
1476
        op->o_req_ndn = be->be_nsuffix[0];
 
1477
 
 
1478
        op->ors_scope = LDAP_SCOPE_SUBTREE;
 
1479
        op->ors_deref = LDAP_DEREF_NEVER;
 
1480
        op->ors_limit = NULL;
 
1481
        op->ors_tlimit = SLAP_NO_LIMIT;
 
1482
        op->ors_slimit = SLAP_NO_LIMIT;
 
1483
        op->ors_attrs =  slap_anlist_no_attrs;
 
1484
 
 
1485
        op->o_bd = select_backend(&op->o_req_ndn, 0);
 
1486
 
 
1487
        ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
 
1488
        for (agd = agi->agi_def ; agd ; agd = agd->agd_next) {
 
1489
 
 
1490
                autogroup_build_def_filter(agd, op);
 
1491
 
 
1492
 
 
1493
                ags.ags_info = agi;
 
1494
                ags.ags_def = agd;
 
1495
                cb.sc_private = &ags;
 
1496
                cb.sc_response = autogroup_group_add_cb;
 
1497
                cb.sc_cleanup = NULL;
 
1498
                cb.sc_next = NULL;
 
1499
 
 
1500
                op->o_callback = &cb;
 
1501
 
 
1502
                op->o_bd->bd_info = (BackendInfo *)on->on_info;
 
1503
                op->o_bd->be_search( op, &rs );
 
1504
                op->o_bd->bd_info = (BackendInfo *)on;
 
1505
 
 
1506
                filter_free_x( op, op->ors_filter );
 
1507
                op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
 
1508
        }               
 
1509
        ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
 
1510
 
 
1511
        return 0;
 
1512
}
 
1513
 
 
1514
static int
 
1515
autogroup_db_close(
 
1516
        BackendDB       *be,
 
1517
        ConfigReply     *cr )
 
1518
{
 
1519
        slap_overinst                   *on = (slap_overinst *) be->bd_info;
 
1520
 
 
1521
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_close\n", 0, 0, 0);
 
1522
 
 
1523
        if ( on->on_bi.bi_private ) {
 
1524
                autogroup_info_t                *agi = on->on_bi.bi_private;
 
1525
                autogroup_entry_t       *age = agi->agi_entry,
 
1526
                                        *age_next;
 
1527
                autogroup_filter_t      *agf, *agf_next;
 
1528
 
 
1529
                for ( age_next = age; age_next; age = age_next ) {
 
1530
                        age_next = age->age_next;
 
1531
 
 
1532
                        ch_free( age->age_dn.bv_val );
 
1533
                        ch_free( age->age_ndn.bv_val );
 
1534
 
 
1535
                        agf = age->age_filter;
 
1536
 
 
1537
                        for ( agf_next = agf; agf_next; agf = agf_next ) {
 
1538
                                agf_next = agf->agf_next;
 
1539
 
 
1540
                                filter_free( agf->agf_filter );
 
1541
                                ch_free( agf->agf_filterstr.bv_val );
 
1542
                                ch_free( agf->agf_dn.bv_val );
 
1543
                                ch_free( agf->agf_ndn.bv_val ); 
 
1544
                                ch_free( agf );
 
1545
                        }
 
1546
 
 
1547
                        ldap_pvt_thread_mutex_destroy( &age->age_mutex );
 
1548
                        ch_free( age );
 
1549
                }
 
1550
        }
 
1551
 
 
1552
        return 0;
 
1553
}
 
1554
 
 
1555
static int
 
1556
autogroup_db_destroy(
 
1557
        BackendDB       *be,
 
1558
        ConfigReply     *cr )
 
1559
{
 
1560
        slap_overinst                   *on = (slap_overinst *) be->bd_info;
 
1561
 
 
1562
        Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_destroy\n", 0, 0, 0);
 
1563
 
 
1564
        if ( on->on_bi.bi_private ) {
 
1565
                autogroup_info_t                *agi = on->on_bi.bi_private;
 
1566
                autogroup_def_t         *agd = agi->agi_def,
 
1567
                                        *agd_next;
 
1568
 
 
1569
                for ( agd_next = agd; agd_next; agd = agd_next ) {
 
1570
                        agd_next = agd->agd_next;
 
1571
 
 
1572
                        ch_free( agd );
 
1573
                }
 
1574
 
 
1575
                ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
 
1576
                ch_free( agi );
 
1577
        }
 
1578
 
 
1579
        return 0;
 
1580
}
 
1581
 
 
1582
static slap_overinst    autogroup = { { NULL } };
 
1583
 
 
1584
static
 
1585
int
 
1586
autogroup_initialize(void)
 
1587
{
 
1588
        int             rc = 0;
 
1589
        autogroup.on_bi.bi_type = "autogroup";
 
1590
 
 
1591
        autogroup.on_bi.bi_db_open = autogroup_db_open;
 
1592
        autogroup.on_bi.bi_db_close = autogroup_db_close;
 
1593
        autogroup.on_bi.bi_db_destroy = autogroup_db_destroy;
 
1594
 
 
1595
        autogroup.on_bi.bi_op_add = autogroup_add_entry;
 
1596
        autogroup.on_bi.bi_op_delete = autogroup_delete_entry;
 
1597
        autogroup.on_bi.bi_op_modify = autogroup_modify_entry;
 
1598
 
 
1599
        autogroup.on_response = autogroup_response;
 
1600
 
 
1601
        autogroup.on_bi.bi_cf_ocs = agocs;
 
1602
 
 
1603
        rc = config_register_schema( agcfg, agocs );
 
1604
        if ( rc ) {
 
1605
                return rc;
 
1606
        }
 
1607
 
 
1608
        return overlay_register( &autogroup );
 
1609
}
 
1610
 
 
1611
int
 
1612
init_module( int argc, char *argv[] )
 
1613
{
 
1614
        return autogroup_initialize();
 
1615
}