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