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 $ */
4
* Copyright 2007 MichaÅ SzulczyÅski.
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted only as authorized by the OpenLDAP
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>.
20
#include <ac/string.h>
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;
33
struct autogroup_filter_t *agf_next;
36
/* Description of group attributes. */
37
typedef struct autogroup_def_t {
39
AttributeDescription *agd_member_url_ad;
40
AttributeDescription *agd_member_ad;
41
struct autogroup_def_t *agd_next;
44
/* Represents the group entry. */
45
typedef struct autogroup_entry_t {
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;
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;
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. */
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. */
73
Modifications *agg_mod; /* Used in autogroup_member_search_modify_cb to hold the
74
search results which will be added to the group. */
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. */
82
** dn, ndn - the DN of the member to add
83
** age - the group to which the member DN will be added
86
autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
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 };
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);
99
assert( ndn != NULL );
102
BER_BVZERO( &vals[ 1 ] );
104
BER_BVZERO( &nvals[ 1 ] );
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;
115
o.o_tag = LDAP_REQ_MODIFY;
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;
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;
128
return sreply.sr_err;
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.
137
autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
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 };
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);
150
modlist.sml_values = NULL;
151
modlist.sml_nvalues = NULL;
152
modlist.sml_numvals = 0;
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);
158
BER_BVZERO( &vals[ 1 ] );
160
BER_BVZERO( &nvals[ 1 ] );
162
modlist.sml_values = vals;
163
modlist.sml_nvalues = nvals;
164
modlist.sml_numvals = 1;
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;
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;
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;
187
return sreply.sr_err;
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
197
autogroup_member_search_cb( Operation *op, SlapReply *rs )
199
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
201
assert( op->o_tag == LDAP_REQ_SEARCH );
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;
207
const char *text = NULL;
209
struct berval vals[ 2 ], nvals[ 2 ];
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);
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 ] );
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;
226
modify_add_values( agg->agg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
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
239
autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
241
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
243
assert( op->o_tag == LDAP_REQ_SEARCH );
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;
249
Modifications *modlist;
250
SlapReply sreply = {REP_RESULT};
251
const char *text = NULL;
253
struct berval vals[ 2 ], nvals[ 2 ];
254
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
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);
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 ] );
264
modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
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;
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;
274
modlist->sml_flags = SLAP_MOD_INTERNAL;
275
modlist->sml_next = NULL;
277
if ( agg->agg_mod == NULL ) {
278
agg->agg_mod = modlist;
279
agg->agg_mod_last = modlist;
281
agg->agg_mod_last->sml_next = modlist;
282
agg->agg_mod_last = modlist;
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
301
autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *age, autogroup_filter_t *agf, int modify)
303
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
305
SlapReply rs = { REP_SEARCH };
306
slap_callback cb = { 0 };
307
slap_callback null_cb = { NULL, slap_null_cb, NULL, NULL };
310
Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n",
311
age->age_dn.bv_val, 0, 0);
314
o.o_tag = LDAP_REQ_SEARCH;
316
o.o_req_dn = agf->agf_dn;
317
o.o_req_ndn = agf->agf_ndn;
319
o.ors_filterstr = agf->agf_filterstr;
320
o.ors_filter = agf->agf_filter;
322
o.ors_scope = agf->agf_scope;
323
o.ors_deref = LDAP_DEREF_NEVER;
325
o.ors_tlimit = SLAP_NO_LIMIT;
326
o.ors_slimit = SLAP_NO_LIMIT;
327
o.ors_attrs = slap_anlist_no_attrs;
331
agg.agg_mod_last = NULL;
333
cb.sc_private = &agg;
336
cb.sc_response = autogroup_member_search_modify_cb;
338
cb.sc_response = autogroup_member_search_cb;
341
cb.sc_cleanup = NULL;
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;
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;
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;
365
slap_mods_free(agg.agg_mod, 1);
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
382
autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd, Entry *e, BerValue *ndn, int scan, int modify)
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;
390
int rc = 0, match = 1, null_entry = 0;
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);
402
Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_group <%s>\n",
403
e->e_name.bv_val, 0, 0);
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 );
409
Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0);
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;
422
ber_dupbv( &(*agep)->age_dn, &e->e_name );
423
ber_dupbv( &(*agep)->age_ndn, &e->e_nname );
425
a = attrs_find( e->e_attrs, agd->agd_member_url_ad );
427
if ( null_entry == 1 ) {
429
overlay_entry_release_ov( op, e, 0, on );
433
Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group has no memberURL\n", 0,0,0);
435
for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
437
agf = (autogroup_filter_t*)ch_calloc( 1, sizeof( autogroup_filter_t ) );
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);
446
agf->agf_scope = lud->lud_scope;
448
if ( lud->lud_dn == NULL ) {
449
BER_BVSTR( &dn, "" );
451
ber_str2bv( lud->lud_dn, 0, 0, &dn );
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);
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 );
466
agf->agf_next = NULL;
469
if( (*agep)->age_filter == NULL ) {
470
(*agep)->age_filter = agf;
473
if( agf_prev != NULL ) {
474
agf_prev->agf_next = agf;
480
autogroup_add_members_from_filter( op, e, (*agep), agf, modify );
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);
486
ldap_free_urldesc( lud );
493
ldap_free_urldesc( lud );
498
if ( null_entry == 1 ) {
505
** Used when opening the database to add all existing
506
** groups from the database to our internal list.
509
autogroup_group_add_cb( Operation *op, SlapReply *rs )
511
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
513
assert( op->o_tag == LDAP_REQ_SEARCH );
516
if ( rs->sr_type == REP_SEARCH ) {
517
autogroup_sc_t *ags = (autogroup_sc_t *)op->o_callback->sc_private;
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);
522
autogroup_add_group( op, ags->ags_info, ags->ags_def, rs->sr_entry, NULL, 0, 0);
530
** When adding a group, we first strip any existing members,
531
** and add all which match the filters ourselfs.
534
autogroup_add_entry( Operation *op, SlapReply *rs)
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;
544
Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n",
545
op->ora_e->e_name.bv_val, 0, 0);
547
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
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 ) ) {
553
const char *text = NULL;
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;
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 ) );
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;
571
for ( ; age ; age = age->age_next ) {
572
ldap_pvt_thread_mutex_lock( &age->age_mutex );
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. */
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 );
586
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
589
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
591
return SLAP_CB_CONTINUE;
595
** agi - internal group and attribute definitions list
596
** e - the group to remove from the internal list
599
autogroup_delete_group( autogroup_info_t *agi, autogroup_entry_t *e )
601
autogroup_entry_t *age = agi->agi_entry,
606
Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_group <%s>\n",
607
age->age_dn.bv_val, 0, 0);
609
for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
610
age_next = age->age_next;
613
autogroup_filter_t *agf = age->age_filter,
616
if ( age_prev != NULL ) {
617
age_prev->age_next = age_next;
619
agi->agi_entry = NULL;
622
ch_free( age->age_dn.bv_val );
623
ch_free( age->age_ndn.bv_val );
625
for( agf_next = agf ; agf_next ; agf = agf_next ){
626
agf_next = agf->agf_next;
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 );
634
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
635
ldap_pvt_thread_mutex_destroy( &age->age_mutex );
644
Debug( LDAP_DEBUG_TRACE, "autogroup_delete_group: group <%s> not found, should not happen\n", age->age_dn.bv_val, 0, 0);
651
autogroup_delete_entry( Operation *op, SlapReply *rs)
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;
660
int matched_group = 0, rc = 0;
662
Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
664
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
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;
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;
678
if ( is_entry_objectclass_or_sub( e, age->age_def->agd_oc ) ) {
683
dnMatch( &match, 0, NULL, NULL, &e->e_nname, &age->age_ndn );
686
autogroup_filter_t *agf = age->age_filter,
689
autogroup_delete_group( agi, age );
694
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
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;
703
/* Check if the entry matches any of the groups.
704
If yes, we can delete the entry from that group. */
706
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
707
ldap_pvt_thread_mutex_lock( &age->age_mutex );
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 );
718
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
721
overlay_entry_release_ov( op, e, 0, on );
722
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
724
return SLAP_CB_CONTINUE;
728
autogroup_response( Operation *op, SlapReply *rs )
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;
738
int is_olddn, is_newdn, dn_equal;
740
if ( op->o_tag == LDAP_REQ_MODRDN ) {
741
if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
743
Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
745
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
747
if ( op->oq_modrdn.rs_newSup ) {
748
pdn = *op->oq_modrdn.rs_newSup;
750
dnParent( &op->o_req_dn, &pdn );
752
build_new_dn( &new_dn, &pdn, &op->orr_newrdn, op->o_tmpmemctx );
754
if ( op->oq_modrdn.rs_nnewSup ) {
755
pdn = *op->oq_modrdn.rs_nnewSup;
757
dnParent( &op->o_req_ndn, &pdn );
759
build_new_dn( &new_ndn, &pdn, &op->orr_nnewrdn, op->o_tmpmemctx );
761
Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN to <%s>\n", new_dn.bv_val, 0, 0);
763
dnMatch( &dn_equal, 0, NULL, NULL, &op->o_req_ndn, &new_ndn );
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;
772
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
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;
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 ) {
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 )
792
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
795
dnMatch( &match, 0, NULL, NULL, &age->age_ndn, &op->o_req_ndn );
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 );
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;
812
overlay_entry_release_ov( op, e, 0, on );
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
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.
824
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
829
ldap_pvt_thread_mutex_lock( &age->age_mutex );
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);
835
op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
836
op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
838
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
839
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
840
return SLAP_CB_CONTINUE;
843
a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
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 )
856
overlay_entry_release_ov( op, group, 0, on );
858
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
859
if ( dnIsSuffix( &new_ndn, &agf->agf_ndn ) ) {
866
if ( is_olddn == 1 && is_newdn == 0 ) {
867
autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
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 );
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 );
882
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
885
op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
886
op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
888
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
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);
896
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
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;
905
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
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;
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 ) {
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 )
931
for ( ; age ; age = age->age_next ) {
932
ldap_pvt_thread_mutex_lock( &age->age_mutex );
934
dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
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);
943
overlay_entry_release_ov( op, e, 0, on );
945
autogroup_delete_member_from_group( op, NULL, NULL, age );
946
autogroup_delete_group( agi, age );
948
autogroup_add_group( op, agi, group_agd, NULL, &op->o_req_ndn, 1, 1);
950
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
951
return SLAP_CB_CONTINUE;
955
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
959
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
962
overlay_entry_release_ov( op, e, 0, on );
963
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
964
return SLAP_CB_CONTINUE;
968
overlay_entry_release_ov( op, e, 0, on );
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.
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.
979
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
984
ldap_pvt_thread_mutex_lock( &age->age_mutex );
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);
991
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
992
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
993
return SLAP_CB_CONTINUE;
996
a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
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 )
1009
overlay_entry_release_ov( op, group, 0, on );
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 ) {
1020
if ( is_olddn == 1 && is_newdn == 0 ) {
1021
autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1023
if ( is_olddn == 0 && is_newdn == 1 ) {
1024
autogroup_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, age );
1027
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
1030
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1034
return SLAP_CB_CONTINUE;
1038
** When modifing a group, we must deny any modifications to the member attribute,
1039
** because the group would be inconsistent.
1042
autogroup_modify_entry( Operation *op, SlapReply *rs)
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;
1051
if ( get_manageDSAit( op ) ) {
1052
return SLAP_CB_CONTINUE;
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 );
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;
1065
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
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;
1074
for ( ; agd; agd = agd->agd_next ) {
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 )
1085
m = op->orm_modlist;
1087
for ( ; age ; age = age->age_next ) {
1088
dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
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;
1104
overlay_entry_release_ov( op, e, 0, on );
1105
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1106
return SLAP_CB_CONTINUE;
1110
overlay_entry_release_ov( op, e, 0, on );
1111
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1112
return SLAP_CB_CONTINUE;
1116
** Builds a filter for searching for the
1117
** group entries, according to the objectClass.
1120
autogroup_build_def_filter( autogroup_def_t *agd, Operation *op )
1124
Debug( LDAP_DEBUG_TRACE, "==> autogroup_build_def_filter\n", 0, 0, 0);
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 );
1131
ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
1133
ptr = lutil_strcopy( ptr, agd->agd_oc->soc_cname.bv_val );
1137
op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
1139
assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );
1149
static ConfigDriver ag_cfgen;
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' )",
1160
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
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 },
1175
ag_cfgen( ConfigArgs *c )
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;
1184
Debug( LDAP_DEBUG_TRACE, "==> autogroup_cfgen\n", 0, 0, 0);
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;
1195
age = agi->agi_entry;
1197
if ( c->op == SLAP_CONFIG_EMIT ) {
1199
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1201
for ( i = 0 ; agd ; i++, agd = agd->agd_next ) {
1203
char *ptr = c->cr_msg;
1205
assert(agd->agd_oc != NULL);
1206
assert(agd->agd_member_url_ad != NULL);
1207
assert(agd->agd_member_ad != NULL);
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 );
1215
bv.bv_val = c->cr_msg;
1216
bv.bv_len = ptr - bv.bv_val;
1217
value_add_one ( &c->rvalue_vals, &bv );
1220
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1224
}else if ( c->op == LDAP_MOD_DELETE ) {
1226
autogroup_def_t *agd_next;
1227
autogroup_entry_t *age_next;
1228
autogroup_filter_t *agf = age->age_filter,
1231
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1233
for ( agd_next = agd; agd_next; agd = agd_next ) {
1234
agd_next = agd->agd_next;
1239
for ( age_next = age ; age_next ; age = age_next ) {
1240
age_next = age->age_next;
1242
ch_free( age->age_dn.bv_val );
1243
ch_free( age->age_ndn.bv_val );
1245
for( agf_next = agf ; agf_next ; agf = agf_next ){
1246
agf_next = agf->agf_next;
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 );
1254
ldap_pvt_thread_mutex_init( &age->age_mutex );
1258
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1260
ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
1262
on->on_bi.bi_private = NULL;
1265
autogroup_def_t **agdp;
1266
autogroup_entry_t *age_next, *age_prev;
1267
autogroup_filter_t *agf,
1271
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1273
for ( i = 0, agdp = &agi->agi_def;
1276
if ( *agdp == NULL) {
1279
agdp = &(*agdp)->agd_next;
1283
*agdp = agd->agd_next;
1285
for ( age_next = age , age_prev = NULL ; age_next ; age_prev = age, age = age_next ) {
1286
age_next = age->age_next;
1288
if( age->age_def == agd ) {
1289
agf = age->age_filter;
1291
ch_free( age->age_dn.bv_val );
1292
ch_free( age->age_ndn.bv_val );
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 );
1302
ldap_pvt_thread_mutex_destroy( &age->age_mutex );
1307
if( age_prev != NULL ) {
1308
age_prev->age_next = age_next;
1315
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1324
autogroup_def_t **agdp,
1326
ObjectClass *oc = NULL;
1327
AttributeDescription *member_url_ad = NULL,
1332
oc = oc_find( c->argv[ 1 ] );
1334
snprintf( c->cr_msg, sizeof( c->cr_msg ),
1335
"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
1336
"unable to find ObjectClass \"%s\"",
1338
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1339
c->log, c->cr_msg, 0 );
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\"",
1350
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1351
c->log, c->cr_msg, 0 );
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\"",
1361
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1362
c->log, c->cr_msg, 0 );
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\"",
1372
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1373
c->log, c->cr_msg, 0 );
1377
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1379
for ( agdp = &agi->agi_def ; *agdp ; agdp = &(*agdp)->agd_next ) {
1380
/* The same URL attribute / member attribute pair
1381
* cannot be repeated */
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*/
1394
if ( c->valx > 0 ) {
1397
for ( i = 0, agdp = &agi->agi_def ;
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}",
1405
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
1406
c->log, c->cr_msg, 0 );
1408
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1411
agdp = &(*agdp)->agd_next;
1416
for ( agdp = &agi->agi_def; *agdp;
1417
agdp = &(*agdp)->agd_next )
1421
*agdp = (autogroup_def_t *)ch_calloc( 1, sizeof(autogroup_info_t));
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;
1428
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1441
** Do a search for all the groups in the
1442
** database, and add them to out internal list.
1449
slap_overinst *on = (slap_overinst *) be->bd_info,
1451
autogroup_info_t *agi = on->on_bi.bi_private;
1452
autogroup_def_t *agd;
1455
SlapReply rs = { REP_RESULT };
1456
slap_callback cb = { 0 };
1458
void *thrctx = ldap_pvt_thread_pool_context();
1459
Connection conn = { 0 };
1460
OperationBuffer opbuf;
1465
Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_open\n", 0, 0, 0);
1467
connection_fake_init( &conn, &opbuf, thrctx );
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;
1475
op->o_req_dn = be->be_suffix[0];
1476
op->o_req_ndn = be->be_nsuffix[0];
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;
1485
op->o_bd = select_backend(&op->o_req_ndn, 0);
1487
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
1488
for (agd = agi->agi_def ; agd ; agd = agd->agd_next) {
1490
autogroup_build_def_filter(agd, op);
1495
cb.sc_private = &ags;
1496
cb.sc_response = autogroup_group_add_cb;
1497
cb.sc_cleanup = NULL;
1500
op->o_callback = &cb;
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;
1506
filter_free_x( op, op->ors_filter );
1507
op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
1509
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
1519
slap_overinst *on = (slap_overinst *) be->bd_info;
1521
Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_close\n", 0, 0, 0);
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,
1527
autogroup_filter_t *agf, *agf_next;
1529
for ( age_next = age; age_next; age = age_next ) {
1530
age_next = age->age_next;
1532
ch_free( age->age_dn.bv_val );
1533
ch_free( age->age_ndn.bv_val );
1535
agf = age->age_filter;
1537
for ( agf_next = agf; agf_next; agf = agf_next ) {
1538
agf_next = agf->agf_next;
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 );
1547
ldap_pvt_thread_mutex_destroy( &age->age_mutex );
1556
autogroup_db_destroy(
1560
slap_overinst *on = (slap_overinst *) be->bd_info;
1562
Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_destroy\n", 0, 0, 0);
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,
1569
for ( agd_next = agd; agd_next; agd = agd_next ) {
1570
agd_next = agd->agd_next;
1575
ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
1582
static slap_overinst autogroup = { { NULL } };
1586
autogroup_initialize(void)
1589
autogroup.on_bi.bi_type = "autogroup";
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;
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;
1599
autogroup.on_response = autogroup_response;
1601
autogroup.on_bi.bi_cf_ocs = agocs;
1603
rc = config_register_schema( agcfg, agocs );
1608
return overlay_register( &autogroup );
1612
init_module( int argc, char *argv[] )
1614
return autogroup_initialize();