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