Home | History | Annotate | Line # | Download | only in autogroup
autogroup.c revision 1.1.1.4
      1  1.1.1.2  lukem /*	$NetBSD: autogroup.c,v 1.1.1.4 2014/05/28 09:58:27 tron Exp $	*/
      2  1.1.1.2  lukem 
      3      1.1  lukem /* autogroup.c - automatic group overlay */
      4  1.1.1.4   tron /* $OpenLDAP$ */
      5  1.1.1.2  lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  1.1.1.2  lukem  *
      7  1.1.1.4   tron  * Copyright 2007-2014 The OpenLDAP Foundation.
      8  1.1.1.2  lukem  * Portions Copyright 2007 Micha Szulczyski.
      9  1.1.1.2  lukem  * Portions Copyright 2009 Howard Chu.
     10      1.1  lukem  * All rights reserved.
     11      1.1  lukem  *
     12      1.1  lukem  * Redistribution and use in source and binary forms, with or without
     13      1.1  lukem  * modification, are permitted only as authorized by the OpenLDAP
     14      1.1  lukem  * Public License.
     15      1.1  lukem  *
     16      1.1  lukem  * A copy of this license is available in the file LICENSE in the
     17      1.1  lukem  * top-level directory of the distribution or, alternatively, at
     18      1.1  lukem  * <http://www.OpenLDAP.org/license.html>.
     19      1.1  lukem  */
     20  1.1.1.2  lukem /* ACKNOWLEDGEMENTS:
     21  1.1.1.2  lukem  * This work was initially developed by Micha Szulczyski for inclusion in
     22  1.1.1.2  lukem  * OpenLDAP Software.  Additional significant contributors include:
     23  1.1.1.2  lukem  *   Howard Chu
     24  1.1.1.4   tron  *   Raphael Ouazana
     25  1.1.1.4   tron  *   Norbert Pueschel
     26  1.1.1.4   tron  *   Christian Manal
     27  1.1.1.2  lukem  */
     28      1.1  lukem 
     29      1.1  lukem #include "portable.h"
     30      1.1  lukem 
     31      1.1  lukem #include <stdio.h>
     32      1.1  lukem 
     33      1.1  lukem #include <ac/string.h>
     34      1.1  lukem 
     35      1.1  lukem #include "slap.h"
     36      1.1  lukem #include "config.h"
     37      1.1  lukem #include "lutil.h"
     38      1.1  lukem 
     39  1.1.1.4   tron #ifndef SLAPD_MEMBEROF_ATTR
     40  1.1.1.4   tron #define	SLAPD_MEMBEROF_ATTR	"memberOf"
     41  1.1.1.4   tron #endif
     42  1.1.1.4   tron 
     43      1.1  lukem /* Filter represents the memberURL of a group. */
     44      1.1  lukem typedef struct autogroup_filter_t {
     45      1.1  lukem 	struct berval			agf_dn;	/* The base DN in memberURL */
     46      1.1  lukem 	struct berval			agf_ndn;
     47      1.1  lukem 	struct berval			agf_filterstr;
     48      1.1  lukem 	Filter				*agf_filter;
     49      1.1  lukem 	int				agf_scope;
     50  1.1.1.4   tron 	AttributeName			*agf_anlist;
     51      1.1  lukem 	struct autogroup_filter_t	*agf_next;
     52      1.1  lukem } autogroup_filter_t;
     53      1.1  lukem 
     54      1.1  lukem /* Description of group attributes. */
     55      1.1  lukem typedef struct autogroup_def_t {
     56      1.1  lukem 	ObjectClass		*agd_oc;
     57      1.1  lukem 	AttributeDescription	*agd_member_url_ad;
     58      1.1  lukem 	AttributeDescription	*agd_member_ad;
     59      1.1  lukem 	struct autogroup_def_t	*agd_next;
     60      1.1  lukem } autogroup_def_t;
     61      1.1  lukem 
     62      1.1  lukem /* Represents the group entry. */
     63      1.1  lukem typedef struct autogroup_entry_t {
     64      1.1  lukem 	BerValue		age_dn;
     65      1.1  lukem 	BerValue		age_ndn;
     66      1.1  lukem 	autogroup_filter_t	*age_filter; /* List of filters made from memberURLs */
     67      1.1  lukem 	autogroup_def_t		*age_def; /* Attribute definition */
     68      1.1  lukem 	ldap_pvt_thread_mutex_t age_mutex;
     69  1.1.1.4   tron 	int			age_mustrefresh; /* Defined in request to refresh in response */
     70  1.1.1.4   tron 	int			age_modrdn_olddnmodified; /* Defined in request to refresh in response */
     71      1.1  lukem 	struct autogroup_entry_t	*age_next;
     72      1.1  lukem } autogroup_entry_t;
     73      1.1  lukem 
     74      1.1  lukem /* Holds pointers to attribute definitions and groups. */
     75      1.1  lukem typedef struct autogroup_info_t {
     76      1.1  lukem 	autogroup_def_t		*agi_def;	/* Group attributes definitions. */
     77      1.1  lukem 	autogroup_entry_t	*agi_entry;	/* Group entries.  */
     78  1.1.1.4   tron 	AttributeDescription	*agi_memberof_ad;	/* memberOf attribute description  */
     79      1.1  lukem 	ldap_pvt_thread_mutex_t agi_mutex;
     80      1.1  lukem } autogroup_info_t;
     81      1.1  lukem 
     82      1.1  lukem /* Search callback for adding groups initially. */
     83      1.1  lukem typedef struct autogroup_sc_t {
     84      1.1  lukem 	autogroup_info_t		*ags_info;	/* Group definitions and entries.  */
     85      1.1  lukem 	autogroup_def_t		*ags_def;	/* Attributes definition of the group being added. */
     86      1.1  lukem } autogroup_sc_t;
     87      1.1  lukem 
     88      1.1  lukem /* Used for adding members, found when searching, to a group. */
     89      1.1  lukem typedef struct autogroup_ga_t {
     90      1.1  lukem 	autogroup_entry_t	*agg_group;	/* The group to which the members will be added. */
     91  1.1.1.4   tron 	autogroup_filter_t	*agg_filter;	/* Current filter */
     92      1.1  lukem 	Entry			*agg_entry;	/* Used in autogroup_member_search_cb to modify
     93      1.1  lukem 						this entry with the search results. */
     94      1.1  lukem 
     95      1.1  lukem 	Modifications		*agg_mod;	/* Used in autogroup_member_search_modify_cb to hold the
     96      1.1  lukem 						search results which will be added to the group. */
     97      1.1  lukem 
     98      1.1  lukem 	Modifications		*agg_mod_last; /* Used in autogroup_member_search_modify_cb so we don't
     99      1.1  lukem 						have to search for the last mod added. */
    100      1.1  lukem } autogroup_ga_t;
    101      1.1  lukem 
    102      1.1  lukem 
    103      1.1  lukem /*
    104      1.1  lukem **	dn, ndn	- the DN of the member to add
    105      1.1  lukem **	age	- the group to which the member DN will be added
    106      1.1  lukem */
    107      1.1  lukem static int
    108      1.1  lukem autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
    109      1.1  lukem {
    110      1.1  lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    111  1.1.1.4   tron 	Modifications	*modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
    112      1.1  lukem 	SlapReply	sreply = {REP_RESULT};
    113  1.1.1.4   tron 	BerValue	*vals, *nvals;
    114      1.1  lukem 	slap_callback	cb = { NULL, slap_null_cb, NULL, NULL };
    115      1.1  lukem 	Operation	o = *op;
    116      1.1  lukem 
    117      1.1  lukem 	assert( dn != NULL );
    118      1.1  lukem 	assert( ndn != NULL );
    119  1.1.1.4   tron 	Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_to_group adding <%s> to <%s>\n",
    120  1.1.1.4   tron 		dn->bv_val, age->age_dn.bv_val, 0);
    121      1.1  lukem 
    122  1.1.1.4   tron 	vals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
    123  1.1.1.4   tron 	nvals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
    124  1.1.1.4   tron 	ber_dupbv( vals, dn );
    125      1.1  lukem 	BER_BVZERO( &vals[ 1 ] );
    126  1.1.1.4   tron 	ber_dupbv( nvals, ndn );
    127      1.1  lukem 	BER_BVZERO( &nvals[ 1 ] );
    128      1.1  lukem 
    129  1.1.1.4   tron 	modlist->sml_op = LDAP_MOD_ADD;
    130  1.1.1.4   tron 	modlist->sml_desc = age->age_def->agd_member_ad;
    131  1.1.1.4   tron 	modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
    132  1.1.1.4   tron 	modlist->sml_values = vals;
    133  1.1.1.4   tron 	modlist->sml_nvalues = nvals;
    134  1.1.1.4   tron 	modlist->sml_numvals = 1;
    135  1.1.1.4   tron 	modlist->sml_flags = SLAP_MOD_INTERNAL;
    136  1.1.1.4   tron 	modlist->sml_next = NULL;
    137  1.1.1.4   tron 
    138  1.1.1.4   tron 	o.o_tag = LDAP_REQ_MODIFY;
    139  1.1.1.4   tron 	o.o_callback = &cb;
    140  1.1.1.4   tron 	o.orm_modlist = modlist;
    141  1.1.1.4   tron 	o.o_req_dn = age->age_dn;
    142  1.1.1.4   tron 	o.o_req_ndn = age->age_ndn;
    143  1.1.1.4   tron 	o.o_permissive_modify = 1;
    144  1.1.1.4   tron 	o.o_managedsait = SLAP_CONTROL_CRITICAL;
    145  1.1.1.4   tron 	o.o_relax = SLAP_CONTROL_CRITICAL;
    146  1.1.1.4   tron 
    147  1.1.1.4   tron 	o.o_bd->bd_info = (BackendInfo *)on->on_info;
    148  1.1.1.4   tron 	(void)op->o_bd->be_modify( &o, &sreply );
    149  1.1.1.4   tron 	o.o_bd->bd_info = (BackendInfo *)on;
    150  1.1.1.4   tron 
    151  1.1.1.4   tron 	slap_mods_free( modlist, 1 );
    152  1.1.1.4   tron 
    153  1.1.1.4   tron 	return sreply.sr_err;
    154  1.1.1.4   tron }
    155  1.1.1.4   tron 
    156  1.1.1.4   tron /*
    157  1.1.1.4   tron **	e	- the entry where to get the attribute values
    158  1.1.1.4   tron **	age	- the group to which the values will be added
    159  1.1.1.4   tron */
    160  1.1.1.4   tron static int
    161  1.1.1.4   tron autogroup_add_member_values_to_group( Operation *op, Entry *e, autogroup_entry_t *age, AttributeDescription *attrdesc )
    162  1.1.1.4   tron {
    163  1.1.1.4   tron 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    164  1.1.1.4   tron 	Modifications	modlist;
    165  1.1.1.4   tron 	SlapReply	sreply = {REP_RESULT};
    166  1.1.1.4   tron 	Attribute	*attr;
    167  1.1.1.4   tron 	slap_callback	cb = { NULL, slap_null_cb, NULL, NULL };
    168  1.1.1.4   tron 	Operation	o = *op;
    169  1.1.1.4   tron 
    170  1.1.1.4   tron 	assert( e != NULL );
    171  1.1.1.4   tron 	Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_values_to_group adding <%s> to <%s>\n",
    172  1.1.1.4   tron 		e->e_name.bv_val, age->age_dn.bv_val, 0);
    173  1.1.1.4   tron 
    174  1.1.1.4   tron 	attr = attrs_find( e->e_attrs, attrdesc );
    175  1.1.1.4   tron 	if (!attr) {
    176  1.1.1.4   tron 		// Nothing to add
    177  1.1.1.4   tron 		return LDAP_SUCCESS;
    178  1.1.1.4   tron 	}
    179  1.1.1.4   tron 
    180      1.1  lukem 	modlist.sml_op = LDAP_MOD_ADD;
    181      1.1  lukem 	modlist.sml_desc = age->age_def->agd_member_ad;
    182      1.1  lukem 	modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
    183  1.1.1.4   tron 	modlist.sml_values = attr->a_vals;
    184  1.1.1.4   tron 	modlist.sml_nvalues = attr->a_nvals;
    185  1.1.1.4   tron 	modlist.sml_numvals = attr->a_numvals;
    186      1.1  lukem 	modlist.sml_flags = SLAP_MOD_INTERNAL;
    187      1.1  lukem 	modlist.sml_next = NULL;
    188      1.1  lukem 
    189      1.1  lukem 	o.o_tag = LDAP_REQ_MODIFY;
    190      1.1  lukem 	o.o_callback = &cb;
    191      1.1  lukem 	o.orm_modlist = &modlist;
    192      1.1  lukem 	o.o_req_dn = age->age_dn;
    193      1.1  lukem 	o.o_req_ndn = age->age_ndn;
    194      1.1  lukem 	o.o_permissive_modify = 1;
    195      1.1  lukem 	o.o_managedsait = SLAP_CONTROL_CRITICAL;
    196      1.1  lukem 	o.o_relax = SLAP_CONTROL_CRITICAL;
    197      1.1  lukem 
    198      1.1  lukem 	o.o_bd->bd_info = (BackendInfo *)on->on_info;
    199      1.1  lukem 	(void)op->o_bd->be_modify( &o, &sreply );
    200      1.1  lukem 	o.o_bd->bd_info = (BackendInfo *)on;
    201      1.1  lukem 
    202      1.1  lukem 	return sreply.sr_err;
    203      1.1  lukem }
    204      1.1  lukem 
    205      1.1  lukem /*
    206      1.1  lukem ** dn,ndn	- the DN to be deleted
    207      1.1  lukem ** age		- the group from which the DN will be deleted
    208      1.1  lukem ** If we pass a NULL dn and ndn, all members are deleted from the group.
    209      1.1  lukem */
    210      1.1  lukem static int
    211      1.1  lukem autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
    212      1.1  lukem {
    213      1.1  lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    214  1.1.1.4   tron 	Modifications	*modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
    215      1.1  lukem 	SlapReply	sreply = {REP_RESULT};
    216  1.1.1.4   tron 	BerValue	*vals, *nvals;
    217      1.1  lukem 	slap_callback	cb = { NULL, slap_null_cb, NULL, NULL };
    218      1.1  lukem 	Operation	o = *op;
    219      1.1  lukem 
    220      1.1  lukem 	if ( dn == NULL || ndn == NULL ) {
    221      1.1  lukem 		Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing all members from <%s>\n",
    222      1.1  lukem 			age->age_dn.bv_val, 0 ,0);
    223      1.1  lukem 
    224  1.1.1.4   tron 		modlist->sml_values = NULL;
    225  1.1.1.4   tron 		modlist->sml_nvalues = NULL;
    226  1.1.1.4   tron 		modlist->sml_numvals = 0;
    227      1.1  lukem 	} else {
    228      1.1  lukem 		Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing <%s> from <%s>\n",
    229      1.1  lukem 			dn->bv_val, age->age_dn.bv_val, 0);
    230      1.1  lukem 
    231  1.1.1.4   tron 		vals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
    232  1.1.1.4   tron 		nvals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
    233  1.1.1.4   tron 		ber_dupbv( vals, dn );
    234      1.1  lukem 		BER_BVZERO( &vals[ 1 ] );
    235  1.1.1.4   tron 		ber_dupbv( nvals, ndn );
    236      1.1  lukem 		BER_BVZERO( &nvals[ 1 ] );
    237      1.1  lukem 
    238  1.1.1.4   tron 		modlist->sml_values = vals;
    239  1.1.1.4   tron 		modlist->sml_nvalues = nvals;
    240  1.1.1.4   tron 		modlist->sml_numvals = 1;
    241      1.1  lukem 	}
    242      1.1  lukem 
    243      1.1  lukem 
    244  1.1.1.4   tron 	modlist->sml_op = LDAP_MOD_DELETE;
    245  1.1.1.4   tron 	modlist->sml_desc = age->age_def->agd_member_ad;
    246  1.1.1.4   tron 	modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
    247  1.1.1.4   tron 	modlist->sml_flags = SLAP_MOD_INTERNAL;
    248  1.1.1.4   tron 	modlist->sml_next = NULL;
    249      1.1  lukem 
    250      1.1  lukem 	o.o_callback = &cb;
    251      1.1  lukem 	o.o_tag = LDAP_REQ_MODIFY;
    252  1.1.1.4   tron 	o.orm_modlist = modlist;
    253      1.1  lukem 	o.o_req_dn = age->age_dn;
    254      1.1  lukem 	o.o_req_ndn = age->age_ndn;
    255      1.1  lukem 	o.o_relax = SLAP_CONTROL_CRITICAL;
    256      1.1  lukem 	o.o_managedsait = SLAP_CONTROL_CRITICAL;
    257      1.1  lukem 	o.o_permissive_modify = 1;
    258      1.1  lukem 
    259      1.1  lukem 	o.o_bd->bd_info = (BackendInfo *)on->on_info;
    260      1.1  lukem 	(void)op->o_bd->be_modify( &o, &sreply );
    261      1.1  lukem 	o.o_bd->bd_info = (BackendInfo *)on;
    262      1.1  lukem 
    263  1.1.1.4   tron 	slap_mods_free( modlist, 1 );
    264  1.1.1.4   tron 
    265      1.1  lukem 	return sreply.sr_err;
    266      1.1  lukem }
    267      1.1  lukem 
    268  1.1.1.4   tron /*
    269  1.1.1.4   tron **      e       - the entry where to get the attribute values
    270  1.1.1.4   tron **      age     - the group from which the values will be deleted
    271  1.1.1.4   tron */
    272  1.1.1.4   tron static int
    273  1.1.1.4   tron autogroup_delete_member_values_from_group( Operation *op, Entry *e, autogroup_entry_t *age, AttributeDescription *attrdesc )
    274  1.1.1.4   tron {
    275  1.1.1.4   tron         slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
    276  1.1.1.4   tron         Modifications   modlist;
    277  1.1.1.4   tron         SlapReply       sreply = {REP_RESULT};
    278  1.1.1.4   tron         Attribute       *attr;
    279  1.1.1.4   tron         slap_callback   cb = { NULL, slap_null_cb, NULL, NULL };
    280  1.1.1.4   tron         Operation       o = *op;
    281  1.1.1.4   tron 
    282  1.1.1.4   tron         assert( e != NULL );
    283  1.1.1.4   tron         Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_values_from_group removing <%s> from <%s>\n",
    284  1.1.1.4   tron                 e->e_name.bv_val, age->age_dn.bv_val, 0);
    285  1.1.1.4   tron 
    286  1.1.1.4   tron         attr = attrs_find( e->e_attrs, attrdesc );
    287  1.1.1.4   tron         if (!attr) {
    288  1.1.1.4   tron                 // Nothing to add
    289  1.1.1.4   tron                 return LDAP_SUCCESS;
    290  1.1.1.4   tron         }
    291  1.1.1.4   tron 
    292  1.1.1.4   tron         modlist.sml_op = LDAP_MOD_DELETE;
    293  1.1.1.4   tron         modlist.sml_desc = age->age_def->agd_member_ad;
    294  1.1.1.4   tron         modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
    295  1.1.1.4   tron         modlist.sml_values = attr->a_vals;
    296  1.1.1.4   tron         modlist.sml_nvalues = attr->a_nvals;
    297  1.1.1.4   tron         modlist.sml_numvals = attr->a_numvals;
    298  1.1.1.4   tron         modlist.sml_flags = SLAP_MOD_INTERNAL;
    299  1.1.1.4   tron         modlist.sml_next = NULL;
    300  1.1.1.4   tron 
    301  1.1.1.4   tron         o.o_tag = LDAP_REQ_MODIFY;
    302  1.1.1.4   tron         o.o_callback = &cb;
    303  1.1.1.4   tron         o.orm_modlist = &modlist;
    304  1.1.1.4   tron         o.o_req_dn = age->age_dn;
    305  1.1.1.4   tron         o.o_req_ndn = age->age_ndn;
    306  1.1.1.4   tron         o.o_permissive_modify = 1;
    307  1.1.1.4   tron         o.o_managedsait = SLAP_CONTROL_CRITICAL;
    308  1.1.1.4   tron         o.o_relax = SLAP_CONTROL_CRITICAL;
    309  1.1.1.4   tron 
    310  1.1.1.4   tron         o.o_bd->bd_info = (BackendInfo *)on->on_info;
    311  1.1.1.4   tron         (void)op->o_bd->be_modify( &o, &sreply );
    312  1.1.1.4   tron         o.o_bd->bd_info = (BackendInfo *)on;
    313  1.1.1.4   tron 
    314  1.1.1.4   tron         return sreply.sr_err;
    315  1.1.1.4   tron }
    316  1.1.1.4   tron 
    317      1.1  lukem /*
    318      1.1  lukem ** Callback used to add entries to a group,
    319      1.1  lukem ** which are going to be written in the database
    320      1.1  lukem ** (used in bi_op_add)
    321      1.1  lukem ** The group is passed in autogroup_ga_t->agg_group
    322      1.1  lukem */
    323      1.1  lukem static int
    324      1.1  lukem autogroup_member_search_cb( Operation *op, SlapReply *rs )
    325      1.1  lukem {
    326      1.1  lukem 	assert( op->o_tag == LDAP_REQ_SEARCH );
    327      1.1  lukem 
    328      1.1  lukem 	if ( rs->sr_type == REP_SEARCH ) {
    329      1.1  lukem 		autogroup_ga_t		*agg = (autogroup_ga_t *)op->o_callback->sc_private;
    330      1.1  lukem 		autogroup_entry_t	*age = agg->agg_group;
    331  1.1.1.4   tron 		autogroup_filter_t	*agf = agg->agg_filter;
    332      1.1  lukem 		Modification		mod;
    333      1.1  lukem 		const char		*text = NULL;
    334      1.1  lukem 		char			textbuf[1024];
    335  1.1.1.4   tron 		struct berval		*vals, *nvals;
    336  1.1.1.4   tron 		struct berval		lvals[ 2 ], lnvals[ 2 ];
    337  1.1.1.4   tron 		int			numvals;
    338      1.1  lukem 
    339      1.1  lukem 		Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_cb <%s>\n",
    340      1.1  lukem 			rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
    341      1.1  lukem 
    342  1.1.1.4   tron 		if ( agf->agf_anlist ) {
    343  1.1.1.4   tron 			Attribute *attr = attrs_find( rs->sr_entry->e_attrs, agf->agf_anlist[0].an_desc );
    344  1.1.1.4   tron 			if (attr) {
    345  1.1.1.4   tron 				vals = attr->a_vals;
    346  1.1.1.4   tron 				nvals = attr->a_nvals;
    347  1.1.1.4   tron 				numvals = attr->a_numvals;
    348  1.1.1.4   tron 			} else {
    349  1.1.1.4   tron 				// Nothing to add
    350  1.1.1.4   tron 				return 0;
    351  1.1.1.4   tron 			}
    352  1.1.1.4   tron 		} else {
    353  1.1.1.4   tron 			lvals[ 0 ] = rs->sr_entry->e_name;
    354  1.1.1.4   tron 			BER_BVZERO( &lvals[ 1 ] );
    355  1.1.1.4   tron 			lnvals[ 0 ] = rs->sr_entry->e_nname;
    356  1.1.1.4   tron 			BER_BVZERO( &lnvals[ 1 ] );
    357  1.1.1.4   tron 			vals = lvals;
    358  1.1.1.4   tron 			nvals = lnvals;
    359  1.1.1.4   tron 			numvals = 1;
    360  1.1.1.4   tron 		}
    361      1.1  lukem 
    362      1.1  lukem 		mod.sm_op = LDAP_MOD_ADD;
    363      1.1  lukem 		mod.sm_desc = age->age_def->agd_member_ad;
    364      1.1  lukem 		mod.sm_type = age->age_def->agd_member_ad->ad_cname;
    365      1.1  lukem 		mod.sm_values = vals;
    366      1.1  lukem 		mod.sm_nvalues = nvals;
    367  1.1.1.4   tron 		mod.sm_numvals = numvals;
    368      1.1  lukem 
    369      1.1  lukem 		modify_add_values( agg->agg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
    370      1.1  lukem 	}
    371      1.1  lukem 
    372      1.1  lukem 	return 0;
    373      1.1  lukem }
    374      1.1  lukem 
    375      1.1  lukem /*
    376      1.1  lukem ** Callback used to add entries to a group, which is already in the database.
    377      1.1  lukem ** (used in on_response)
    378      1.1  lukem ** The group is passed in autogroup_ga_t->agg_group
    379      1.1  lukem ** NOTE: Very slow.
    380      1.1  lukem */
    381      1.1  lukem static int
    382      1.1  lukem autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
    383      1.1  lukem {
    384      1.1  lukem 	assert( op->o_tag == LDAP_REQ_SEARCH );
    385      1.1  lukem 
    386      1.1  lukem 	if ( rs->sr_type == REP_SEARCH ) {
    387      1.1  lukem 		autogroup_ga_t		*agg = (autogroup_ga_t *)op->o_callback->sc_private;
    388      1.1  lukem 		autogroup_entry_t	*age = agg->agg_group;
    389  1.1.1.4   tron 		autogroup_filter_t	*agf = agg->agg_filter;
    390      1.1  lukem 		Modifications		*modlist;
    391  1.1.1.4   tron 		struct berval		*vals, *nvals;
    392  1.1.1.4   tron 		struct berval		lvals[ 2 ], lnvals[ 2 ];
    393  1.1.1.4   tron 		int			numvals;
    394      1.1  lukem 
    395      1.1  lukem 		Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_modify_cb <%s>\n",
    396      1.1  lukem 			rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
    397      1.1  lukem 
    398  1.1.1.4   tron 		if ( agf->agf_anlist ) {
    399  1.1.1.4   tron 			Attribute *attr = attrs_find( rs->sr_entry->e_attrs, agf->agf_anlist[0].an_desc );
    400  1.1.1.4   tron 			if (attr) {
    401  1.1.1.4   tron 				vals = attr->a_vals;
    402  1.1.1.4   tron 				nvals = attr->a_nvals;
    403  1.1.1.4   tron 				numvals = attr->a_numvals;
    404  1.1.1.4   tron 			} else {
    405  1.1.1.4   tron 				// Nothing to add
    406  1.1.1.4   tron 				return 0;
    407  1.1.1.4   tron 			}
    408      1.1  lukem 		} else {
    409  1.1.1.4   tron 			lvals[ 0 ] = rs->sr_entry->e_name;
    410  1.1.1.4   tron 			BER_BVZERO( &lvals[ 1 ] );
    411  1.1.1.4   tron 			lnvals[ 0 ] = rs->sr_entry->e_nname;
    412  1.1.1.4   tron 			BER_BVZERO( &lnvals[ 1 ] );
    413  1.1.1.4   tron 			vals = lvals;
    414  1.1.1.4   tron 			nvals = lnvals;
    415  1.1.1.4   tron 			numvals = 1;
    416  1.1.1.4   tron 		}
    417  1.1.1.4   tron 
    418  1.1.1.4   tron 		if ( numvals ) {
    419  1.1.1.4   tron 			modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
    420  1.1.1.4   tron 
    421  1.1.1.4   tron 			modlist->sml_op = LDAP_MOD_ADD;
    422  1.1.1.4   tron 			modlist->sml_desc = age->age_def->agd_member_ad;
    423  1.1.1.4   tron 			modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
    424  1.1.1.4   tron 
    425  1.1.1.4   tron 			ber_bvarray_dup_x( &modlist->sml_values, vals, NULL );
    426  1.1.1.4   tron 			ber_bvarray_dup_x( &modlist->sml_nvalues, nvals, NULL );
    427  1.1.1.4   tron 			modlist->sml_numvals = numvals;
    428  1.1.1.4   tron 
    429  1.1.1.4   tron 			modlist->sml_flags = SLAP_MOD_INTERNAL;
    430  1.1.1.4   tron 			modlist->sml_next = NULL;
    431  1.1.1.4   tron 
    432  1.1.1.4   tron 			if ( agg->agg_mod == NULL ) {
    433  1.1.1.4   tron 				agg->agg_mod = modlist;
    434  1.1.1.4   tron 				agg->agg_mod_last = modlist;
    435  1.1.1.4   tron 			} else {
    436  1.1.1.4   tron 				agg->agg_mod_last->sml_next = modlist;
    437  1.1.1.4   tron 				agg->agg_mod_last = modlist;
    438  1.1.1.4   tron 			}
    439      1.1  lukem 		}
    440      1.1  lukem 
    441      1.1  lukem 	}
    442      1.1  lukem 
    443      1.1  lukem 	return 0;
    444      1.1  lukem }
    445      1.1  lukem 
    446      1.1  lukem 
    447      1.1  lukem /*
    448      1.1  lukem ** Adds all entries matching the passed filter to the specified group.
    449      1.1  lukem ** If modify == 1, then we modify the group's entry in the database using be_modify.
    450      1.1  lukem ** If modify == 0, then, we must supply a rw entry for the group,
    451      1.1  lukem **	because we only modify the entry, without calling be_modify.
    452      1.1  lukem ** e	- the group entry, to which the members will be added
    453      1.1  lukem ** age	- the group
    454      1.1  lukem ** agf	- the filter
    455      1.1  lukem */
    456      1.1  lukem static int
    457      1.1  lukem autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *age, autogroup_filter_t *agf, int modify)
    458      1.1  lukem {
    459      1.1  lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
    460      1.1  lukem 	Operation		o = *op;
    461      1.1  lukem 	SlapReply		rs = { REP_SEARCH };
    462      1.1  lukem 	slap_callback		cb = { 0 };
    463      1.1  lukem 	slap_callback		null_cb = { NULL, slap_null_cb, NULL, NULL };
    464      1.1  lukem 	autogroup_ga_t		agg;
    465      1.1  lukem 
    466      1.1  lukem 	Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n",
    467      1.1  lukem 		age->age_dn.bv_val, 0, 0);
    468      1.1  lukem 
    469      1.1  lukem 	o.ors_attrsonly = 0;
    470      1.1  lukem 	o.o_tag = LDAP_REQ_SEARCH;
    471      1.1  lukem 
    472      1.1  lukem 	o.o_req_dn = agf->agf_dn;
    473      1.1  lukem 	o.o_req_ndn = agf->agf_ndn;
    474      1.1  lukem 
    475      1.1  lukem 	o.ors_filterstr = agf->agf_filterstr;
    476      1.1  lukem 	o.ors_filter = agf->agf_filter;
    477      1.1  lukem 
    478      1.1  lukem 	o.ors_scope = agf->agf_scope;
    479      1.1  lukem 	o.ors_deref = LDAP_DEREF_NEVER;
    480      1.1  lukem 	o.ors_limit = NULL;
    481      1.1  lukem 	o.ors_tlimit = SLAP_NO_LIMIT;
    482      1.1  lukem 	o.ors_slimit = SLAP_NO_LIMIT;
    483  1.1.1.4   tron 	o.ors_attrs =  agf->agf_anlist ? agf->agf_anlist : slap_anlist_no_attrs;
    484      1.1  lukem 
    485      1.1  lukem 	agg.agg_group = age;
    486  1.1.1.4   tron 	agg.agg_filter = agf;
    487      1.1  lukem 	agg.agg_mod = NULL;
    488      1.1  lukem 	agg.agg_mod_last = NULL;
    489      1.1  lukem 	agg.agg_entry = e;
    490      1.1  lukem 	cb.sc_private = &agg;
    491      1.1  lukem 
    492      1.1  lukem 	if ( modify == 1 ) {
    493      1.1  lukem 		cb.sc_response = autogroup_member_search_modify_cb;
    494      1.1  lukem 	} else {
    495      1.1  lukem 		cb.sc_response = autogroup_member_search_cb;
    496      1.1  lukem 	}
    497      1.1  lukem 
    498      1.1  lukem 	cb.sc_cleanup = NULL;
    499      1.1  lukem 	cb.sc_next = NULL;
    500      1.1  lukem 
    501      1.1  lukem 	o.o_callback = &cb;
    502      1.1  lukem 
    503      1.1  lukem 	o.o_bd->bd_info = (BackendInfo *)on->on_info;
    504      1.1  lukem 	op->o_bd->be_search( &o, &rs );
    505      1.1  lukem 	o.o_bd->bd_info = (BackendInfo *)on;
    506      1.1  lukem 
    507  1.1.1.4   tron 	if ( modify == 1 && agg.agg_mod ) {
    508  1.1.1.4   tron 		rs_reinit( &rs, REP_RESULT );
    509  1.1.1.4   tron 
    510      1.1  lukem 		o = *op;
    511      1.1  lukem 		o.o_callback = &null_cb;
    512      1.1  lukem 		o.o_tag = LDAP_REQ_MODIFY;
    513      1.1  lukem 		o.orm_modlist = agg.agg_mod;
    514      1.1  lukem 		o.o_req_dn = age->age_dn;
    515      1.1  lukem 		o.o_req_ndn = age->age_ndn;
    516      1.1  lukem 		o.o_relax = SLAP_CONTROL_CRITICAL;
    517      1.1  lukem 		o.o_managedsait = SLAP_CONTROL_NONCRITICAL;
    518      1.1  lukem 		o.o_permissive_modify = 1;
    519      1.1  lukem 
    520      1.1  lukem 		o.o_bd->bd_info = (BackendInfo *)on->on_info;
    521      1.1  lukem 		(void)op->o_bd->be_modify( &o, &rs );
    522      1.1  lukem 		o.o_bd->bd_info = (BackendInfo *)on;
    523      1.1  lukem 
    524      1.1  lukem 		slap_mods_free(agg.agg_mod, 1);
    525      1.1  lukem 	}
    526      1.1  lukem 
    527      1.1  lukem 	return 0;
    528      1.1  lukem }
    529      1.1  lukem 
    530      1.1  lukem /*
    531      1.1  lukem ** Adds a group to the internal list from the passed entry.
    532      1.1  lukem ** scan specifies whether to add all maching members to the group.
    533      1.1  lukem ** modify specifies whether to modify the given group entry (when modify == 0),
    534      1.1  lukem **	or to modify the group entry in the database (when modify == 1 and e = NULL and ndn != NULL).
    535      1.1  lukem ** agi	- pointer to the groups and the attribute definitions
    536      1.1  lukem ** agd - the attribute definition of the added group
    537      1.1  lukem ** e	- the entry representing the group, can be NULL if the ndn is specified, and modify == 1
    538      1.1  lukem ** ndn	- the DN of the group, can be NULL if we give a non-NULL e
    539      1.1  lukem */
    540      1.1  lukem static int
    541      1.1  lukem autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd, Entry *e, BerValue *ndn, int scan, int modify)
    542      1.1  lukem {
    543      1.1  lukem 	autogroup_entry_t	**agep = &agi->agi_entry;
    544      1.1  lukem 	autogroup_filter_t	*agf, *agf_prev = NULL;
    545      1.1  lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
    546      1.1  lukem 	LDAPURLDesc		*lud = NULL;
    547      1.1  lukem 	Attribute		*a;
    548      1.1  lukem 	BerValue		*bv, dn;
    549      1.1  lukem 	int			rc = 0, match = 1, null_entry = 0;
    550      1.1  lukem 
    551      1.1  lukem 	if ( e == NULL ) {
    552      1.1  lukem 		if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) !=
    553      1.1  lukem 			LDAP_SUCCESS || e == NULL ) {
    554      1.1  lukem 			Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot get entry for <%s>\n", ndn->bv_val, 0, 0);
    555      1.1  lukem 			return 1;
    556      1.1  lukem 		}
    557      1.1  lukem 
    558      1.1  lukem 		null_entry = 1;
    559      1.1  lukem 	}
    560      1.1  lukem 
    561      1.1  lukem 	Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_group <%s>\n",
    562      1.1  lukem 		e->e_name.bv_val, 0, 0);
    563      1.1  lukem 
    564      1.1  lukem 	if ( agi->agi_entry != NULL ) {
    565      1.1  lukem 		for ( ; *agep ; agep = &(*agep)->age_next ) {
    566      1.1  lukem 			dnMatch( &match, 0, NULL, NULL, &e->e_nname, &(*agep)->age_ndn );
    567      1.1  lukem 			if ( match == 0 ) {
    568      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0);
    569      1.1  lukem 				return 1;
    570      1.1  lukem 			}
    571      1.1  lukem 			/* goto last */;
    572      1.1  lukem 		}
    573      1.1  lukem 	}
    574      1.1  lukem 
    575      1.1  lukem 
    576      1.1  lukem 	*agep = (autogroup_entry_t *)ch_calloc( 1, sizeof( autogroup_entry_t ) );
    577      1.1  lukem 	ldap_pvt_thread_mutex_init( &(*agep)->age_mutex );
    578      1.1  lukem 	(*agep)->age_def = agd;
    579      1.1  lukem 	(*agep)->age_filter = NULL;
    580  1.1.1.4   tron 	(*agep)->age_mustrefresh = 0;
    581  1.1.1.4   tron 	(*agep)->age_modrdn_olddnmodified = 0;
    582      1.1  lukem 
    583      1.1  lukem 	ber_dupbv( &(*agep)->age_dn, &e->e_name );
    584      1.1  lukem 	ber_dupbv( &(*agep)->age_ndn, &e->e_nname );
    585      1.1  lukem 
    586      1.1  lukem 	a = attrs_find( e->e_attrs, agd->agd_member_url_ad );
    587      1.1  lukem 
    588      1.1  lukem 	if ( null_entry == 1 ) {
    589      1.1  lukem 		a = attrs_dup( a );
    590      1.1  lukem 		overlay_entry_release_ov( op, e, 0, on );
    591      1.1  lukem 	}
    592      1.1  lukem 
    593      1.1  lukem 	if( a == NULL ) {
    594      1.1  lukem 		Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: group has no memberURL\n", 0,0,0);
    595      1.1  lukem 	} else {
    596      1.1  lukem 		for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
    597      1.1  lukem 
    598      1.1  lukem 			agf = (autogroup_filter_t*)ch_calloc( 1, sizeof( autogroup_filter_t ) );
    599      1.1  lukem 
    600      1.1  lukem 			if ( ldap_url_parse( bv->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
    601      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot parse url <%s>\n", bv->bv_val,0,0);
    602      1.1  lukem 				/* FIXME: error? */
    603      1.1  lukem 				ch_free( agf );
    604      1.1  lukem 				continue;
    605      1.1  lukem 			}
    606      1.1  lukem 
    607      1.1  lukem 			agf->agf_scope = lud->lud_scope;
    608      1.1  lukem 
    609      1.1  lukem 			if ( lud->lud_dn == NULL ) {
    610      1.1  lukem 				BER_BVSTR( &dn, "" );
    611      1.1  lukem 			} else {
    612      1.1  lukem 				ber_str2bv( lud->lud_dn, 0, 0, &dn );
    613      1.1  lukem 			}
    614      1.1  lukem 
    615      1.1  lukem 			rc = dnPrettyNormal( NULL, &dn, &agf->agf_dn, &agf->agf_ndn, NULL );
    616      1.1  lukem 			if ( rc != LDAP_SUCCESS ) {
    617      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: cannot normalize DN <%s>\n", dn.bv_val,0,0);
    618      1.1  lukem 				/* FIXME: error? */
    619      1.1  lukem 				goto cleanup;
    620      1.1  lukem 			}
    621      1.1  lukem 
    622      1.1  lukem 			if ( lud->lud_filter != NULL ) {
    623      1.1  lukem 				ber_str2bv( lud->lud_filter, 0, 1, &agf->agf_filterstr);
    624      1.1  lukem 				agf->agf_filter = str2filter( lud->lud_filter );
    625      1.1  lukem 			}
    626      1.1  lukem 
    627  1.1.1.4   tron 			if ( lud->lud_attrs != NULL ) {
    628  1.1.1.4   tron 				int i;
    629  1.1.1.4   tron 
    630  1.1.1.4   tron 				for ( i=0 ; lud->lud_attrs[i]!=NULL ; i++) {
    631  1.1.1.4   tron 					/* Just counting */;
    632  1.1.1.4   tron 				}
    633  1.1.1.4   tron 
    634  1.1.1.4   tron 				if ( i > 1 ) {
    635  1.1.1.4   tron 					Debug( LDAP_DEBUG_ANY, "autogroup_add_group: too many attributes specified in url <%s>\n",
    636  1.1.1.4   tron 						bv->bv_val, 0, 0);
    637  1.1.1.4   tron 					/* FIXME: error? */
    638  1.1.1.4   tron 					ldap_free_urldesc( lud );
    639  1.1.1.4   tron 					ch_free( agf );
    640  1.1.1.4   tron 					continue;
    641  1.1.1.4   tron 				}
    642  1.1.1.4   tron 
    643  1.1.1.4   tron 				agf->agf_anlist = str2anlist( NULL, lud->lud_attrs[0], "," );
    644  1.1.1.4   tron 
    645  1.1.1.4   tron 				if ( agf->agf_anlist == NULL ) {
    646  1.1.1.4   tron 					Debug( LDAP_DEBUG_ANY, "autogroup_add_group: unable to find AttributeDescription \"%s\".\n",
    647  1.1.1.4   tron 						lud->lud_attrs[0], 0, 0 );
    648  1.1.1.4   tron 					/* FIXME: error? */
    649  1.1.1.4   tron 					ldap_free_urldesc( lud );
    650  1.1.1.4   tron 					ch_free( agf );
    651  1.1.1.4   tron 					continue;
    652  1.1.1.4   tron 				}
    653  1.1.1.4   tron 			}
    654  1.1.1.4   tron 
    655      1.1  lukem 			agf->agf_next = NULL;
    656      1.1  lukem 
    657      1.1  lukem 
    658      1.1  lukem 			if( (*agep)->age_filter == NULL ) {
    659      1.1  lukem 				(*agep)->age_filter = agf;
    660      1.1  lukem 			}
    661      1.1  lukem 
    662      1.1  lukem 			if( agf_prev != NULL ) {
    663      1.1  lukem 				agf_prev->agf_next = agf;
    664      1.1  lukem 			}
    665      1.1  lukem 
    666      1.1  lukem 			agf_prev = agf;
    667      1.1  lukem 
    668      1.1  lukem 			if ( scan == 1 ){
    669      1.1  lukem 				autogroup_add_members_from_filter( op, e, (*agep), agf, modify );
    670      1.1  lukem 			}
    671      1.1  lukem 
    672      1.1  lukem 			Debug( LDAP_DEBUG_TRACE, "autogroup_add_group: added memberURL DN <%s> with filter <%s>\n",
    673      1.1  lukem 				agf->agf_ndn.bv_val, agf->agf_filterstr.bv_val, 0);
    674      1.1  lukem 
    675      1.1  lukem 			ldap_free_urldesc( lud );
    676      1.1  lukem 
    677      1.1  lukem 			continue;
    678      1.1  lukem 
    679      1.1  lukem 
    680      1.1  lukem cleanup:;
    681      1.1  lukem 
    682      1.1  lukem 			ldap_free_urldesc( lud );
    683      1.1  lukem 			ch_free( agf );
    684      1.1  lukem 		}
    685      1.1  lukem 	}
    686      1.1  lukem 
    687      1.1  lukem 	if ( null_entry == 1 ) {
    688      1.1  lukem 		attrs_free( a );
    689      1.1  lukem 	}
    690      1.1  lukem 	return rc;
    691      1.1  lukem }
    692      1.1  lukem 
    693      1.1  lukem /*
    694      1.1  lukem ** Used when opening the database to add all existing
    695      1.1  lukem ** groups from the database to our internal list.
    696      1.1  lukem */
    697      1.1  lukem static int
    698      1.1  lukem autogroup_group_add_cb( Operation *op, SlapReply *rs )
    699      1.1  lukem {
    700      1.1  lukem 	assert( op->o_tag == LDAP_REQ_SEARCH );
    701      1.1  lukem 
    702      1.1  lukem 	if ( rs->sr_type == REP_SEARCH ) {
    703      1.1  lukem 		autogroup_sc_t		*ags = (autogroup_sc_t *)op->o_callback->sc_private;
    704      1.1  lukem 
    705      1.1  lukem 		Debug(LDAP_DEBUG_TRACE, "==> autogroup_group_add_cb <%s>\n",
    706      1.1  lukem 			rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
    707      1.1  lukem 
    708      1.1  lukem 		autogroup_add_group( op, ags->ags_info, ags->ags_def, rs->sr_entry, NULL, 0, 0);
    709      1.1  lukem 	}
    710      1.1  lukem 
    711      1.1  lukem 	return 0;
    712      1.1  lukem }
    713      1.1  lukem 
    714      1.1  lukem 
    715      1.1  lukem /*
    716      1.1  lukem ** When adding a group, we first strip any existing members,
    717      1.1  lukem ** and add all which match the filters ourselfs.
    718      1.1  lukem */
    719      1.1  lukem static int
    720      1.1  lukem autogroup_add_entry( Operation *op, SlapReply *rs)
    721      1.1  lukem {
    722  1.1.1.4   tron 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
    723  1.1.1.4   tron 	autogroup_info_t	*agi = (autogroup_info_t *)on->on_bi.bi_private;
    724      1.1  lukem 	autogroup_def_t		*agd = agi->agi_def;
    725  1.1.1.4   tron 	autogroup_entry_t	*age;
    726      1.1  lukem 	autogroup_filter_t	*agf;
    727      1.1  lukem 	int			rc = 0;
    728      1.1  lukem 
    729      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n",
    730      1.1  lukem 		op->ora_e->e_name.bv_val, 0, 0);
    731      1.1  lukem 
    732      1.1  lukem 	ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
    733      1.1  lukem 
    734      1.1  lukem 	/* Check if it's a group. */
    735      1.1  lukem 	for ( ; agd ; agd = agd->agd_next ) {
    736      1.1  lukem 		if ( is_entry_objectclass_or_sub( op->ora_e, agd->agd_oc ) ) {
    737      1.1  lukem 			Modification		mod;
    738      1.1  lukem 			const char		*text = NULL;
    739      1.1  lukem 			char			textbuf[1024];
    740      1.1  lukem 
    741      1.1  lukem 			mod.sm_op = LDAP_MOD_DELETE;
    742      1.1  lukem 			mod.sm_desc = agd->agd_member_ad;
    743      1.1  lukem 			mod.sm_type = agd->agd_member_ad->ad_cname;
    744      1.1  lukem 			mod.sm_values = NULL;
    745      1.1  lukem 			mod.sm_nvalues = NULL;
    746      1.1  lukem 
    747      1.1  lukem 			/* We don't want any member attributes added by the user. */
    748      1.1  lukem 			modify_delete_values( op->ora_e, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
    749      1.1  lukem 
    750      1.1  lukem 			autogroup_add_group( op, agi, agd, op->ora_e, NULL, 1 , 0);
    751      1.1  lukem 			ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    752      1.1  lukem 			return SLAP_CB_CONTINUE;
    753      1.1  lukem 		}
    754      1.1  lukem 	}
    755      1.1  lukem 
    756  1.1.1.4   tron 
    757  1.1.1.4   tron 	for ( age = agi->agi_entry; age ; age = age->age_next ) {
    758      1.1  lukem 		ldap_pvt_thread_mutex_lock( &age->age_mutex );
    759      1.1  lukem 
    760      1.1  lukem 		/* Check if any of the filters are the suffix to the entry DN.
    761      1.1  lukem 		   If yes, we can test that filter against the entry. */
    762      1.1  lukem 
    763      1.1  lukem 		for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
    764      1.1  lukem 			if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
    765      1.1  lukem 				rc = test_filter( op, op->ora_e, agf->agf_filter );
    766      1.1  lukem 				if ( rc == LDAP_COMPARE_TRUE ) {
    767  1.1.1.4   tron 					if ( agf->agf_anlist ) {
    768  1.1.1.4   tron 						autogroup_add_member_values_to_group( op, op->ora_e, age, agf->agf_anlist[0].an_desc );
    769  1.1.1.4   tron 					} else {
    770  1.1.1.4   tron 						autogroup_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, age );
    771  1.1.1.4   tron 					}
    772      1.1  lukem 					break;
    773      1.1  lukem 				}
    774      1.1  lukem 			}
    775      1.1  lukem 		}
    776      1.1  lukem 		ldap_pvt_thread_mutex_unlock( &age->age_mutex );
    777      1.1  lukem 	}
    778      1.1  lukem 
    779      1.1  lukem 	ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    780      1.1  lukem 
    781      1.1  lukem 	return SLAP_CB_CONTINUE;
    782      1.1  lukem }
    783      1.1  lukem 
    784      1.1  lukem /*
    785      1.1  lukem ** agi	- internal group and attribute definitions list
    786      1.1  lukem ** e	- the group to remove from the internal list
    787      1.1  lukem */
    788      1.1  lukem static int
    789      1.1  lukem autogroup_delete_group( autogroup_info_t *agi, autogroup_entry_t *e )
    790      1.1  lukem {
    791      1.1  lukem 	autogroup_entry_t	*age = agi->agi_entry,
    792      1.1  lukem 				*age_prev = NULL,
    793      1.1  lukem 				*age_next;
    794      1.1  lukem 	int			rc = 1;
    795      1.1  lukem 
    796      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_group <%s>\n",
    797      1.1  lukem 		age->age_dn.bv_val, 0, 0);
    798      1.1  lukem 
    799      1.1  lukem 	for ( age_next = age ; age_next ; age_prev = age, age = age_next ) {
    800      1.1  lukem 		age_next = age->age_next;
    801      1.1  lukem 
    802      1.1  lukem 		if ( age == e ) {
    803      1.1  lukem 			autogroup_filter_t	*agf = age->age_filter,
    804      1.1  lukem 							*agf_next;
    805      1.1  lukem 
    806      1.1  lukem 			if ( age_prev != NULL ) {
    807      1.1  lukem 				age_prev->age_next = age_next;
    808      1.1  lukem 			} else {
    809      1.1  lukem 				agi->agi_entry = NULL;
    810      1.1  lukem 			}
    811      1.1  lukem 
    812      1.1  lukem 			ch_free( age->age_dn.bv_val );
    813      1.1  lukem 			ch_free( age->age_ndn.bv_val );
    814      1.1  lukem 
    815      1.1  lukem 			for( agf_next = agf ; agf_next ; agf = agf_next ){
    816      1.1  lukem 				agf_next = agf->agf_next;
    817      1.1  lukem 
    818      1.1  lukem 				filter_free( agf->agf_filter );
    819      1.1  lukem 				ch_free( agf->agf_filterstr.bv_val );
    820      1.1  lukem 				ch_free( agf->agf_dn.bv_val );
    821      1.1  lukem 				ch_free( agf->agf_ndn.bv_val );
    822  1.1.1.4   tron 				anlist_free( agf->agf_anlist, 1, NULL );
    823  1.1.1.4   tron 				ch_free( agf );
    824      1.1  lukem 			}
    825      1.1  lukem 
    826      1.1  lukem 			ldap_pvt_thread_mutex_unlock( &age->age_mutex );
    827      1.1  lukem 			ldap_pvt_thread_mutex_destroy( &age->age_mutex );
    828      1.1  lukem 			ch_free( age );
    829      1.1  lukem 
    830      1.1  lukem 			rc = 0;
    831      1.1  lukem 			return rc;
    832      1.1  lukem 
    833      1.1  lukem 		}
    834      1.1  lukem 	}
    835      1.1  lukem 
    836      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);
    837      1.1  lukem 
    838      1.1  lukem 	return rc;
    839      1.1  lukem 
    840      1.1  lukem }
    841      1.1  lukem 
    842      1.1  lukem static int
    843      1.1  lukem autogroup_delete_entry( Operation *op, SlapReply *rs)
    844      1.1  lukem {
    845      1.1  lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
    846  1.1.1.4   tron 	autogroup_info_t	*agi = (autogroup_info_t *)on->on_bi.bi_private;
    847  1.1.1.4   tron 	autogroup_entry_t	*age, *age_prev, *age_next;
    848      1.1  lukem 	autogroup_filter_t	*agf;
    849      1.1  lukem 	Entry			*e;
    850      1.1  lukem 	int			matched_group = 0, rc = 0;
    851      1.1  lukem 
    852      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
    853      1.1  lukem 
    854      1.1  lukem 	ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
    855      1.1  lukem 
    856      1.1  lukem 	if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
    857      1.1  lukem 		LDAP_SUCCESS || e == NULL ) {
    858      1.1  lukem 		Debug( LDAP_DEBUG_TRACE, "autogroup_delete_entry: cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
    859      1.1  lukem 		ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    860      1.1  lukem 		return SLAP_CB_CONTINUE;
    861      1.1  lukem 	}
    862      1.1  lukem 
    863      1.1  lukem 	/* Check if the entry to be deleted is one of our groups. */
    864  1.1.1.4   tron 	for ( age_next = agi->agi_entry ; age_next ; age_prev = age ) {
    865  1.1.1.4   tron 		age = age_next;
    866      1.1  lukem 		ldap_pvt_thread_mutex_lock( &age->age_mutex );
    867      1.1  lukem 		age_next = age->age_next;
    868      1.1  lukem 
    869      1.1  lukem 		if ( is_entry_objectclass_or_sub( e, age->age_def->agd_oc ) ) {
    870      1.1  lukem 			int match = 1;
    871      1.1  lukem 
    872      1.1  lukem 			matched_group = 1;
    873      1.1  lukem 
    874      1.1  lukem 			dnMatch( &match, 0, NULL, NULL, &e->e_nname, &age->age_ndn );
    875      1.1  lukem 
    876      1.1  lukem 			if ( match == 0 ) {
    877      1.1  lukem 				autogroup_delete_group( agi, age );
    878      1.1  lukem 				break;
    879      1.1  lukem 			}
    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 	if ( matched_group == 1 ) {
    886      1.1  lukem 		overlay_entry_release_ov( op, e, 0, on );
    887      1.1  lukem 		ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    888      1.1  lukem 		return SLAP_CB_CONTINUE;
    889      1.1  lukem 	}
    890      1.1  lukem 
    891      1.1  lukem 	/* Check if the entry matches any of the groups.
    892      1.1  lukem 	   If yes, we can delete the entry from that group. */
    893      1.1  lukem 
    894      1.1  lukem 	for ( age = agi->agi_entry ; age ; age = age->age_next ) {
    895      1.1  lukem 		ldap_pvt_thread_mutex_lock( &age->age_mutex );
    896      1.1  lukem 
    897      1.1  lukem 		for ( agf = age->age_filter; agf ; agf = agf->agf_next ) {
    898      1.1  lukem 			if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
    899      1.1  lukem 				rc = test_filter( op, e, agf->agf_filter );
    900      1.1  lukem 				if ( rc == LDAP_COMPARE_TRUE ) {
    901  1.1.1.4   tron 					/* If the attribute is retrieved from the entry, we don't know what to delete
    902  1.1.1.4   tron 					** So the group must be entirely refreshed
    903  1.1.1.4   tron 					** But the refresh can't be done now because the entry is not deleted
    904  1.1.1.4   tron 					** So the group is marked as mustrefresh
    905  1.1.1.4   tron 					*/
    906  1.1.1.4   tron 					if ( agf->agf_anlist ) {
    907  1.1.1.4   tron 						age->age_mustrefresh = 1;
    908  1.1.1.4   tron 					} else {
    909  1.1.1.4   tron 						autogroup_delete_member_from_group( op, &e->e_name, &e->e_nname, age );
    910  1.1.1.4   tron 					}
    911      1.1  lukem 					break;
    912      1.1  lukem 				}
    913      1.1  lukem 			}
    914      1.1  lukem 		}
    915      1.1  lukem 		ldap_pvt_thread_mutex_unlock( &age->age_mutex );
    916      1.1  lukem 	}
    917      1.1  lukem 
    918      1.1  lukem 	overlay_entry_release_ov( op, e, 0, on );
    919      1.1  lukem 	ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    920      1.1  lukem 
    921      1.1  lukem 	return SLAP_CB_CONTINUE;
    922      1.1  lukem }
    923      1.1  lukem 
    924      1.1  lukem static int
    925      1.1  lukem autogroup_response( Operation *op, SlapReply *rs )
    926      1.1  lukem {
    927      1.1  lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
    928  1.1.1.4   tron 	autogroup_info_t	*agi = (autogroup_info_t *)on->on_bi.bi_private;
    929      1.1  lukem 	autogroup_def_t		*agd = agi->agi_def;
    930  1.1.1.4   tron 	autogroup_entry_t	*age;
    931      1.1  lukem 	autogroup_filter_t	*agf;
    932      1.1  lukem 	BerValue		new_dn, new_ndn, pdn;
    933      1.1  lukem 	Entry			*e, *group;
    934  1.1.1.4   tron 	Attribute		*a, *ea;
    935  1.1.1.4   tron 	int			is_olddn, is_newdn, is_value_refresh, dn_equal;
    936      1.1  lukem 
    937  1.1.1.4   tron 	/* Handle all cases where a refresh of the group is needed */
    938  1.1.1.4   tron 	if ( op->o_tag == LDAP_REQ_DELETE || op->o_tag == LDAP_REQ_MODIFY ) {
    939  1.1.1.4   tron 		if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op ) ) {
    940  1.1.1.4   tron 
    941  1.1.1.4   tron 			ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
    942  1.1.1.4   tron 
    943  1.1.1.4   tron 			for ( age = agi->agi_entry ; age ; age = age->age_next ) {
    944  1.1.1.4   tron 				/* Request detected that the group must be refreshed */
    945  1.1.1.4   tron 
    946  1.1.1.4   tron 				ldap_pvt_thread_mutex_lock( &age->age_mutex );
    947  1.1.1.4   tron 
    948  1.1.1.4   tron 				if ( age->age_mustrefresh ) {
    949  1.1.1.4   tron 					autogroup_delete_member_from_group( op, NULL, NULL, age) ;
    950  1.1.1.4   tron 
    951  1.1.1.4   tron 					for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
    952  1.1.1.4   tron 						autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
    953  1.1.1.4   tron 					}
    954  1.1.1.4   tron 				}
    955  1.1.1.4   tron 
    956  1.1.1.4   tron 				ldap_pvt_thread_mutex_unlock( &age->age_mutex );
    957  1.1.1.4   tron 			}
    958  1.1.1.4   tron 
    959  1.1.1.4   tron 			ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    960  1.1.1.4   tron 		}
    961  1.1.1.4   tron 	} else if ( op->o_tag == LDAP_REQ_MODRDN ) {
    962      1.1  lukem 		if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
    963      1.1  lukem 
    964      1.1  lukem 			Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
    965      1.1  lukem 
    966      1.1  lukem 			ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
    967      1.1  lukem 
    968      1.1  lukem 			if ( op->oq_modrdn.rs_newSup ) {
    969      1.1  lukem 				pdn = *op->oq_modrdn.rs_newSup;
    970      1.1  lukem 			} else {
    971      1.1  lukem 				dnParent( &op->o_req_dn, &pdn );
    972      1.1  lukem 			}
    973      1.1  lukem 			build_new_dn( &new_dn, &pdn, &op->orr_newrdn, op->o_tmpmemctx );
    974      1.1  lukem 
    975      1.1  lukem 			if ( op->oq_modrdn.rs_nnewSup ) {
    976      1.1  lukem 				pdn = *op->oq_modrdn.rs_nnewSup;
    977      1.1  lukem 			} else {
    978      1.1  lukem 				dnParent( &op->o_req_ndn, &pdn );
    979      1.1  lukem 			}
    980      1.1  lukem 			build_new_dn( &new_ndn, &pdn, &op->orr_nnewrdn, op->o_tmpmemctx );
    981      1.1  lukem 
    982      1.1  lukem 			Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN to <%s>\n", new_dn.bv_val, 0, 0);
    983      1.1  lukem 
    984      1.1  lukem 			dnMatch( &dn_equal, 0, NULL, NULL, &op->o_req_ndn, &new_ndn );
    985      1.1  lukem 
    986      1.1  lukem 			if ( overlay_entry_get_ov( op, &new_ndn, NULL, NULL, 0, &e, on ) !=
    987      1.1  lukem 				LDAP_SUCCESS || e == NULL ) {
    988      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get entry for <%s>\n", new_dn.bv_val, 0, 0);
    989      1.1  lukem 				ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
    990      1.1  lukem 				return SLAP_CB_CONTINUE;
    991      1.1  lukem 			}
    992      1.1  lukem 
    993      1.1  lukem 			a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
    994      1.1  lukem 
    995      1.1  lukem 
    996      1.1  lukem 			if ( a == NULL ) {
    997      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN entry <%s> has no objectClass\n", new_dn.bv_val, 0, 0);
    998      1.1  lukem 				overlay_entry_release_ov( op, e, 0, on );
    999      1.1  lukem 				ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1000      1.1  lukem 				return SLAP_CB_CONTINUE;
   1001      1.1  lukem 			}
   1002      1.1  lukem 
   1003      1.1  lukem 
   1004      1.1  lukem 			/* If a groups DN is modified, just update age_dn/ndn of that group with the new DN. */
   1005      1.1  lukem 			for ( ; agd; agd = agd->agd_next ) {
   1006      1.1  lukem 
   1007      1.1  lukem 				if ( value_find_ex( slap_schema.si_ad_objectClass,
   1008      1.1  lukem 						SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
   1009      1.1  lukem 						SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
   1010      1.1  lukem 						a->a_nvals, &agd->agd_oc->soc_cname,
   1011      1.1  lukem 						op->o_tmpmemctx ) == 0 )
   1012      1.1  lukem 				{
   1013      1.1  lukem 					for ( age = agi->agi_entry ; age ; age = age->age_next ) {
   1014      1.1  lukem 						int match = 1;
   1015      1.1  lukem 
   1016      1.1  lukem 						dnMatch( &match, 0, NULL, NULL, &age->age_ndn, &op->o_req_ndn );
   1017      1.1  lukem 						if ( match == 0 ) {
   1018      1.1  lukem 							Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN updating group's DN to <%s>\n", new_dn.bv_val, 0, 0);
   1019      1.1  lukem 							ber_dupbv( &age->age_dn, &new_dn );
   1020      1.1  lukem 							ber_dupbv( &age->age_ndn, &new_ndn );
   1021      1.1  lukem 
   1022      1.1  lukem 							op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx  );
   1023      1.1  lukem 							op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
   1024      1.1  lukem 							overlay_entry_release_ov( op, e, 0, on );
   1025      1.1  lukem 							ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1026      1.1  lukem 							return SLAP_CB_CONTINUE;
   1027      1.1  lukem 						}
   1028      1.1  lukem 					}
   1029      1.1  lukem 
   1030      1.1  lukem 				}
   1031      1.1  lukem 			}
   1032      1.1  lukem 
   1033      1.1  lukem 			/* For each group:
   1034      1.1  lukem 			   1. check if the orginal entry's DN is in the group.
   1035      1.1  lukem 			   2. chceck if the any of the group filter's base DN is a suffix of the new DN
   1036      1.1  lukem 
   1037      1.1  lukem 			   If 1 and 2 are both false, we do nothing.
   1038      1.1  lukem 			   If 1 and 2 is true, we remove the old DN from the group, and add the new DN.
   1039      1.1  lukem 			   If 1 is false, and 2 is true, we check the entry against the group's filters,
   1040      1.1  lukem 				and add it's DN to the group.
   1041      1.1  lukem 			   If 1 is true, and 2 is false, we delete the entry's DN from the group.
   1042      1.1  lukem 			*/
   1043      1.1  lukem 			for ( age = agi->agi_entry ; age ; age = age->age_next ) {
   1044      1.1  lukem 				is_olddn = 0;
   1045      1.1  lukem 				is_newdn = 0;
   1046  1.1.1.4   tron 				is_value_refresh = 0;
   1047      1.1  lukem 
   1048      1.1  lukem 
   1049      1.1  lukem 				ldap_pvt_thread_mutex_lock( &age->age_mutex );
   1050      1.1  lukem 
   1051  1.1.1.4   tron 				if ( age->age_filter && age->age_filter->agf_anlist ) {
   1052  1.1.1.4   tron 					ea = attrs_find( e->e_attrs, age->age_filter->agf_anlist[0].an_desc );
   1053  1.1.1.4   tron 				}
   1054  1.1.1.4   tron 				else {
   1055  1.1.1.4   tron 					ea = NULL;
   1056  1.1.1.4   tron 				}
   1057      1.1  lukem 
   1058  1.1.1.4   tron 				if ( age->age_modrdn_olddnmodified ) {
   1059  1.1.1.4   tron 					/* Resquest already marked this group to be updated */
   1060  1.1.1.4   tron 					is_olddn = 1;
   1061  1.1.1.4   tron 					is_value_refresh = 1;
   1062  1.1.1.4   tron 					age->age_modrdn_olddnmodified = 0;
   1063  1.1.1.4   tron 				} else {
   1064  1.1.1.4   tron 
   1065  1.1.1.4   tron 					if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
   1066  1.1.1.4   tron 						LDAP_SUCCESS || group == NULL ) {
   1067  1.1.1.4   tron 						Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get group entry <%s>\n", age->age_dn.bv_val, 0, 0);
   1068      1.1  lukem 
   1069  1.1.1.4   tron 						op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
   1070  1.1.1.4   tron 						op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
   1071      1.1  lukem 
   1072  1.1.1.4   tron 						overlay_entry_release_ov( op, e, 0, on );
   1073  1.1.1.4   tron 						ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1074  1.1.1.4   tron 						ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1075  1.1.1.4   tron 						return SLAP_CB_CONTINUE;
   1076  1.1.1.4   tron 					}
   1077  1.1.1.4   tron 
   1078  1.1.1.4   tron 					a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
   1079  1.1.1.4   tron 
   1080  1.1.1.4   tron 					if ( a != NULL ) {
   1081  1.1.1.4   tron 						if ( value_find_ex( age->age_def->agd_member_ad,
   1082  1.1.1.4   tron 								SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
   1083  1.1.1.4   tron 								SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
   1084  1.1.1.4   tron 								a->a_nvals, ea ? ea->a_nvals : &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
   1085  1.1.1.4   tron 						{
   1086  1.1.1.4   tron 							is_olddn = 1;
   1087  1.1.1.4   tron 						}
   1088      1.1  lukem 
   1089      1.1  lukem 					}
   1090      1.1  lukem 
   1091  1.1.1.4   tron 					overlay_entry_release_ov( op, group, 0, on );
   1092      1.1  lukem 
   1093  1.1.1.4   tron 				}
   1094      1.1  lukem 
   1095      1.1  lukem 				for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
   1096      1.1  lukem 					if ( dnIsSuffix( &new_ndn, &agf->agf_ndn ) ) {
   1097  1.1.1.4   tron 						/* TODO: should retest filter as it could imply conditions on the dn */
   1098      1.1  lukem 						is_newdn = 1;
   1099      1.1  lukem 						break;
   1100      1.1  lukem 					}
   1101      1.1  lukem 				}
   1102      1.1  lukem 
   1103      1.1  lukem 
   1104  1.1.1.4   tron 				if ( is_value_refresh ) {
   1105  1.1.1.4   tron 					if ( is_olddn != is_newdn ) {
   1106  1.1.1.4   tron 						/* group refresh */
   1107  1.1.1.4   tron 						autogroup_delete_member_from_group( op, NULL, NULL, age) ;
   1108  1.1.1.4   tron 
   1109  1.1.1.4   tron 						for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
   1110  1.1.1.4   tron 							autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
   1111  1.1.1.4   tron 						}
   1112  1.1.1.4   tron 					}
   1113  1.1.1.4   tron 					ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1114  1.1.1.4   tron 					continue;
   1115  1.1.1.4   tron 				}
   1116      1.1  lukem 				if ( is_olddn == 1 && is_newdn == 0 ) {
   1117  1.1.1.4   tron 					if ( ea )
   1118  1.1.1.4   tron 						autogroup_delete_member_values_from_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
   1119  1.1.1.4   tron 					else
   1120  1.1.1.4   tron 						autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
   1121      1.1  lukem 				} else
   1122      1.1  lukem 				if ( is_olddn == 0 && is_newdn == 1 ) {
   1123      1.1  lukem 					for ( agf = age->age_filter; agf; agf = agf->agf_next ) {
   1124      1.1  lukem 						if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
   1125  1.1.1.4   tron 							if ( ea )
   1126  1.1.1.4   tron 								autogroup_add_member_values_to_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
   1127  1.1.1.4   tron 							else
   1128  1.1.1.4   tron 								autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
   1129      1.1  lukem 							break;
   1130      1.1  lukem 						}
   1131      1.1  lukem 					}
   1132      1.1  lukem 				} else
   1133      1.1  lukem 				if ( is_olddn == 1 && is_newdn == 1 && dn_equal != 0 ) {
   1134  1.1.1.4   tron 					if ( ea ) {
   1135  1.1.1.4   tron 						/* group refresh */
   1136  1.1.1.4   tron 						autogroup_delete_member_from_group( op, NULL, NULL, age) ;
   1137  1.1.1.4   tron 
   1138  1.1.1.4   tron 						for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
   1139  1.1.1.4   tron 							autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
   1140  1.1.1.4   tron 						}
   1141  1.1.1.4   tron 					}
   1142  1.1.1.4   tron 					else {
   1143  1.1.1.4   tron 						autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
   1144  1.1.1.4   tron 						autogroup_add_member_to_group( op, &new_dn, &new_ndn, age );
   1145  1.1.1.4   tron 					}
   1146      1.1  lukem 				}
   1147      1.1  lukem 
   1148      1.1  lukem 				ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1149      1.1  lukem 			}
   1150      1.1  lukem 
   1151      1.1  lukem 			op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
   1152      1.1  lukem 			op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
   1153      1.1  lukem 
   1154  1.1.1.4   tron 			overlay_entry_release_ov( op, e, 0, on );
   1155  1.1.1.4   tron 
   1156      1.1  lukem 			ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1157      1.1  lukem 		}
   1158      1.1  lukem 	}
   1159      1.1  lukem 
   1160      1.1  lukem 	if ( op->o_tag == LDAP_REQ_MODIFY ) {
   1161      1.1  lukem 		if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS  && !get_manageDSAit( op ) ) {
   1162      1.1  lukem 			Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODIFY <%s>\n", op->o_req_dn.bv_val, 0, 0);
   1163      1.1  lukem 
   1164      1.1  lukem 			ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
   1165      1.1  lukem 
   1166      1.1  lukem 			if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
   1167      1.1  lukem 				LDAP_SUCCESS || e == NULL ) {
   1168      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
   1169      1.1  lukem 				ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1170      1.1  lukem 				return SLAP_CB_CONTINUE;
   1171      1.1  lukem 			}
   1172      1.1  lukem 
   1173      1.1  lukem 			a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
   1174      1.1  lukem 
   1175      1.1  lukem 
   1176      1.1  lukem 			if ( a == NULL ) {
   1177      1.1  lukem 				Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
   1178      1.1  lukem 				overlay_entry_release_ov( op, e, 0, on );
   1179      1.1  lukem 				ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1180      1.1  lukem 				return SLAP_CB_CONTINUE;
   1181      1.1  lukem 			}
   1182      1.1  lukem 
   1183      1.1  lukem 			/* If we modify a group's memberURL, we have to delete all of it's members,
   1184      1.1  lukem 			   and add them anew, because we cannot tell from which memberURL a member was added. */
   1185      1.1  lukem 			for ( ; agd; agd = agd->agd_next ) {
   1186      1.1  lukem 
   1187      1.1  lukem 				if ( value_find_ex( slap_schema.si_ad_objectClass,
   1188      1.1  lukem 						SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
   1189      1.1  lukem 						SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
   1190      1.1  lukem 						a->a_nvals, &agd->agd_oc->soc_cname,
   1191      1.1  lukem 						op->o_tmpmemctx ) == 0 )
   1192      1.1  lukem 				{
   1193      1.1  lukem 					Modifications	*m;
   1194      1.1  lukem 					int		match = 1;
   1195      1.1  lukem 
   1196      1.1  lukem 					m = op->orm_modlist;
   1197      1.1  lukem 
   1198  1.1.1.4   tron 					for ( age = agi->agi_entry ; age ; age = age->age_next ) {
   1199      1.1  lukem 						ldap_pvt_thread_mutex_lock( &age->age_mutex );
   1200      1.1  lukem 
   1201      1.1  lukem 						dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
   1202      1.1  lukem 
   1203      1.1  lukem 						if ( match == 0 ) {
   1204      1.1  lukem 							for ( ; m ; m = m->sml_next ) {
   1205      1.1  lukem 								if ( m->sml_desc == age->age_def->agd_member_url_ad ) {
   1206      1.1  lukem 									autogroup_def_t	*group_agd = age->age_def;
   1207      1.1  lukem 									Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY changing memberURL for group <%s>\n",
   1208      1.1  lukem 										op->o_req_dn.bv_val, 0, 0);
   1209      1.1  lukem 
   1210      1.1  lukem 									overlay_entry_release_ov( op, e, 0, on );
   1211      1.1  lukem 
   1212      1.1  lukem 									autogroup_delete_member_from_group( op, NULL, NULL, age );
   1213      1.1  lukem 									autogroup_delete_group( agi, age );
   1214      1.1  lukem 
   1215      1.1  lukem 									autogroup_add_group( op, agi, group_agd, NULL, &op->o_req_ndn, 1, 1);
   1216      1.1  lukem 
   1217  1.1.1.4   tron 									overlay_entry_release_ov( op, e, 0, on );
   1218      1.1  lukem 									ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1219      1.1  lukem 									return SLAP_CB_CONTINUE;
   1220      1.1  lukem 								}
   1221      1.1  lukem 							}
   1222      1.1  lukem 
   1223      1.1  lukem 							ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1224      1.1  lukem 							break;
   1225      1.1  lukem 						}
   1226      1.1  lukem 
   1227      1.1  lukem 						ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1228      1.1  lukem 					}
   1229      1.1  lukem 
   1230      1.1  lukem 					overlay_entry_release_ov( op, e, 0, on );
   1231      1.1  lukem 					ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1232      1.1  lukem 					return SLAP_CB_CONTINUE;
   1233      1.1  lukem 				}
   1234      1.1  lukem 			}
   1235      1.1  lukem 
   1236      1.1  lukem 			/* When modifing any of the attributes of an entry, we must
   1237      1.1  lukem 			   check if the entry is in any of our groups, and if
   1238      1.1  lukem 			   the modified entry maches any of the filters of that group.
   1239      1.1  lukem 
   1240      1.1  lukem 			   If the entry exists in a group, but the modified attributes do
   1241      1.1  lukem 				not match any of the group's filters, we delete the entry from that group.
   1242      1.1  lukem 			   If the entry doesn't exist in a group, but matches a filter,
   1243      1.1  lukem 				we add it to that group.
   1244      1.1  lukem 			*/
   1245      1.1  lukem 			for ( age = agi->agi_entry ; age ; age = age->age_next ) {
   1246      1.1  lukem 				is_olddn = 0;
   1247      1.1  lukem 				is_newdn = 0;
   1248      1.1  lukem 
   1249      1.1  lukem 
   1250      1.1  lukem 				ldap_pvt_thread_mutex_lock( &age->age_mutex );
   1251      1.1  lukem 
   1252  1.1.1.4   tron 				if ( age->age_filter && age->age_filter->agf_anlist ) {
   1253  1.1.1.4   tron 					ea = attrs_find( e->e_attrs, age->age_filter->agf_anlist[0].an_desc );
   1254  1.1.1.4   tron 				}
   1255  1.1.1.4   tron 				else {
   1256  1.1.1.4   tron 					ea = NULL;
   1257  1.1.1.4   tron 				}
   1258  1.1.1.4   tron 
   1259      1.1  lukem 				if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
   1260      1.1  lukem 					LDAP_SUCCESS || group == NULL ) {
   1261      1.1  lukem 					Debug( LDAP_DEBUG_TRACE, "autogroup_response MODIFY cannot get entry for <%s>\n",
   1262      1.1  lukem 						age->age_dn.bv_val, 0, 0);
   1263      1.1  lukem 
   1264  1.1.1.4   tron 					overlay_entry_release_ov( op, e, 0, on );
   1265      1.1  lukem 					ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1266      1.1  lukem 					ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1267      1.1  lukem 					return SLAP_CB_CONTINUE;
   1268      1.1  lukem 				}
   1269      1.1  lukem 
   1270      1.1  lukem 				a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
   1271      1.1  lukem 
   1272      1.1  lukem 				if ( a != NULL ) {
   1273      1.1  lukem 					if ( value_find_ex( age->age_def->agd_member_ad,
   1274      1.1  lukem 							SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
   1275      1.1  lukem 							SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
   1276  1.1.1.4   tron 							a->a_nvals, ea ? ea->a_nvals : &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
   1277      1.1  lukem 					{
   1278      1.1  lukem 						is_olddn = 1;
   1279      1.1  lukem 					}
   1280      1.1  lukem 
   1281      1.1  lukem 				}
   1282      1.1  lukem 
   1283      1.1  lukem 				overlay_entry_release_ov( op, group, 0, on );
   1284      1.1  lukem 
   1285      1.1  lukem 				for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
   1286      1.1  lukem 					if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
   1287      1.1  lukem 						if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
   1288      1.1  lukem 							is_newdn = 1;
   1289      1.1  lukem 							break;
   1290      1.1  lukem 						}
   1291      1.1  lukem 					}
   1292      1.1  lukem 				}
   1293      1.1  lukem 
   1294      1.1  lukem 				if ( is_olddn == 1 && is_newdn == 0 ) {
   1295  1.1.1.4   tron 					if(ea)
   1296  1.1.1.4   tron 						autogroup_delete_member_values_from_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
   1297  1.1.1.4   tron 					else
   1298  1.1.1.4   tron 						autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
   1299      1.1  lukem 				} else
   1300      1.1  lukem 				if ( is_olddn == 0 && is_newdn == 1 ) {
   1301  1.1.1.4   tron 					if(ea)
   1302  1.1.1.4   tron 						autogroup_add_member_values_to_group( op, e, age, age->age_filter->agf_anlist[0].an_desc );
   1303  1.1.1.4   tron 					else
   1304  1.1.1.4   tron 						autogroup_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, age );
   1305      1.1  lukem 				}
   1306      1.1  lukem 
   1307      1.1  lukem 				ldap_pvt_thread_mutex_unlock( &age->age_mutex );
   1308      1.1  lukem 			}
   1309      1.1  lukem 
   1310  1.1.1.4   tron 			overlay_entry_release_ov( op, e, 0, on );
   1311  1.1.1.4   tron 
   1312      1.1  lukem 			ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1313      1.1  lukem 		}
   1314      1.1  lukem 	}
   1315      1.1  lukem 
   1316      1.1  lukem 	return SLAP_CB_CONTINUE;
   1317      1.1  lukem }
   1318      1.1  lukem 
   1319      1.1  lukem /*
   1320  1.1.1.4   tron ** Detect if filter contains a memberOf check for dn
   1321  1.1.1.4   tron */
   1322  1.1.1.4   tron static int
   1323  1.1.1.4   tron autogroup_memberOf_filter( Filter *f, BerValue *dn, AttributeDescription *memberof_ad )
   1324  1.1.1.4   tron {
   1325  1.1.1.4   tron 	int result = 0;
   1326  1.1.1.4   tron 	if ( f == NULL ) return 0;
   1327  1.1.1.4   tron 
   1328  1.1.1.4   tron   	switch ( f->f_choice & SLAPD_FILTER_MASK ) {
   1329  1.1.1.4   tron 		case LDAP_FILTER_AND:
   1330  1.1.1.4   tron 		case LDAP_FILTER_OR:
   1331  1.1.1.4   tron 		case LDAP_FILTER_NOT:
   1332  1.1.1.4   tron 			for ( f = f->f_un.f_un_complex; f && !result; f = f->f_next ) {
   1333  1.1.1.4   tron 				result = result || autogroup_memberOf_filter( f, dn, memberof_ad );
   1334  1.1.1.4   tron 			}
   1335  1.1.1.4   tron 			break;
   1336  1.1.1.4   tron 		case LDAP_FILTER_EQUALITY:
   1337  1.1.1.4   tron 			result = ( f->f_ava->aa_desc == memberof_ad &&
   1338  1.1.1.4   tron 			           ber_bvcmp( &f->f_ava->aa_value, dn ) == 0 );
   1339  1.1.1.4   tron 			break;
   1340  1.1.1.4   tron 		default:
   1341  1.1.1.4   tron 			break;
   1342  1.1.1.4   tron 	}
   1343  1.1.1.4   tron 
   1344  1.1.1.4   tron 	return result;
   1345  1.1.1.4   tron }
   1346  1.1.1.4   tron 
   1347  1.1.1.4   tron /*
   1348      1.1  lukem ** When modifing a group, we must deny any modifications to the member attribute,
   1349      1.1  lukem ** because the group would be inconsistent.
   1350      1.1  lukem */
   1351      1.1  lukem static int
   1352      1.1  lukem autogroup_modify_entry( Operation *op, SlapReply *rs)
   1353      1.1  lukem {
   1354      1.1  lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
   1355      1.1  lukem 	autogroup_info_t		*agi = (autogroup_info_t *)on->on_bi.bi_private;
   1356      1.1  lukem 	autogroup_def_t		*agd = agi->agi_def;
   1357  1.1.1.4   tron 	autogroup_entry_t	*age;
   1358      1.1  lukem 	Entry			*e;
   1359      1.1  lukem 	Attribute		*a;
   1360      1.1  lukem 
   1361      1.1  lukem 	if ( get_manageDSAit( op ) ) {
   1362      1.1  lukem 		return SLAP_CB_CONTINUE;
   1363      1.1  lukem 	}
   1364      1.1  lukem 
   1365      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_modify_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
   1366      1.1  lukem 	ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
   1367      1.1  lukem 
   1368      1.1  lukem 	if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
   1369      1.1  lukem 		LDAP_SUCCESS || e == NULL ) {
   1370      1.1  lukem 		Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
   1371      1.1  lukem 		ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1372      1.1  lukem 		return SLAP_CB_CONTINUE;
   1373      1.1  lukem 	}
   1374      1.1  lukem 
   1375  1.1.1.4   tron 	/* Must refresh groups if a matching member value is modified OR filter contains memberOf=DN */
   1376  1.1.1.4   tron 	for ( age = agi->agi_entry; age ; age = age->age_next ) {
   1377  1.1.1.4   tron 		autogroup_filter_t	*agf;
   1378  1.1.1.4   tron 		for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
   1379  1.1.1.4   tron 			if ( agf->agf_anlist ) {
   1380  1.1.1.4   tron 				Modifications	*m;
   1381  1.1.1.4   tron 				for ( m = op->orm_modlist ; m ; m = m->sml_next ) {
   1382  1.1.1.4   tron 					if ( m->sml_desc == agf->agf_anlist[0].an_desc ) {
   1383  1.1.1.4   tron 						if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
   1384  1.1.1.4   tron 							int rc = test_filter( op, e, agf->agf_filter );
   1385  1.1.1.4   tron 							if ( rc == LDAP_COMPARE_TRUE ) {
   1386  1.1.1.4   tron 								age->age_mustrefresh = 1;
   1387  1.1.1.4   tron 							}
   1388  1.1.1.4   tron 						}
   1389  1.1.1.4   tron 					}
   1390  1.1.1.4   tron 				}
   1391  1.1.1.4   tron 			}
   1392  1.1.1.4   tron 
   1393  1.1.1.4   tron 			if ( autogroup_memberOf_filter( agf->agf_filter, &op->o_req_ndn, agi->agi_memberof_ad ) ) {
   1394  1.1.1.4   tron 				age->age_mustrefresh = 1;
   1395  1.1.1.4   tron 			}
   1396  1.1.1.4   tron 		}
   1397  1.1.1.4   tron 	}
   1398  1.1.1.4   tron 
   1399      1.1  lukem 	a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
   1400      1.1  lukem 
   1401      1.1  lukem 	if ( a == NULL ) {
   1402      1.1  lukem 		Debug( LDAP_DEBUG_TRACE, "autogroup_modify_entry entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
   1403      1.1  lukem 		ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1404      1.1  lukem 		return SLAP_CB_CONTINUE;
   1405      1.1  lukem 	}
   1406      1.1  lukem 
   1407      1.1  lukem 
   1408      1.1  lukem 	for ( ; agd; agd = agd->agd_next ) {
   1409      1.1  lukem 
   1410      1.1  lukem 		if ( value_find_ex( slap_schema.si_ad_objectClass,
   1411      1.1  lukem 				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
   1412      1.1  lukem 				SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
   1413      1.1  lukem 				a->a_nvals, &agd->agd_oc->soc_cname,
   1414      1.1  lukem 				op->o_tmpmemctx ) == 0 )
   1415      1.1  lukem 		{
   1416      1.1  lukem 			Modifications	*m;
   1417      1.1  lukem 			int		match = 1;
   1418      1.1  lukem 
   1419      1.1  lukem 			m = op->orm_modlist;
   1420      1.1  lukem 
   1421  1.1.1.4   tron 			for ( age = agi->agi_entry ; age ; age = age->age_next ) {
   1422      1.1  lukem 				dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
   1423      1.1  lukem 
   1424      1.1  lukem 				if ( match == 0 ) {
   1425      1.1  lukem 					for ( ; m ; m = m->sml_next ) {
   1426      1.1  lukem 						if ( m->sml_desc == age->age_def->agd_member_ad ) {
   1427      1.1  lukem 							overlay_entry_release_ov( op, e, 0, on );
   1428      1.1  lukem 							ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1429      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);
   1430      1.1  lukem 							send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to modify dynamic group member attribute");
   1431      1.1  lukem 							return LDAP_CONSTRAINT_VIOLATION;
   1432      1.1  lukem 						}
   1433      1.1  lukem 					}
   1434      1.1  lukem 					break;
   1435      1.1  lukem 				}
   1436      1.1  lukem 			}
   1437      1.1  lukem 
   1438      1.1  lukem 			overlay_entry_release_ov( op, e, 0, on );
   1439      1.1  lukem 			ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1440      1.1  lukem 			return SLAP_CB_CONTINUE;
   1441      1.1  lukem 		}
   1442      1.1  lukem 	}
   1443      1.1  lukem 
   1444      1.1  lukem 	overlay_entry_release_ov( op, e, 0, on );
   1445      1.1  lukem 	ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1446      1.1  lukem 	return SLAP_CB_CONTINUE;
   1447      1.1  lukem }
   1448      1.1  lukem 
   1449  1.1.1.4   tron /*
   1450  1.1.1.4   tron ** Detect if the olddn is part of a group and so if the group should be refreshed
   1451  1.1.1.4   tron */
   1452  1.1.1.4   tron static int
   1453  1.1.1.4   tron autogroup_modrdn_entry( Operation *op, SlapReply *rs)
   1454  1.1.1.4   tron {
   1455  1.1.1.4   tron 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
   1456  1.1.1.4   tron 	autogroup_info_t	*agi = (autogroup_info_t *)on->on_bi.bi_private;
   1457  1.1.1.4   tron 	autogroup_entry_t	*age;
   1458  1.1.1.4   tron 	Entry			*e;
   1459  1.1.1.4   tron 
   1460  1.1.1.4   tron 	if ( get_manageDSAit( op ) ) {
   1461  1.1.1.4   tron 		return SLAP_CB_CONTINUE;
   1462  1.1.1.4   tron 	}
   1463  1.1.1.4   tron 
   1464  1.1.1.4   tron 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_modrdn_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
   1465  1.1.1.4   tron 	ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
   1466  1.1.1.4   tron 
   1467  1.1.1.4   tron 	if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
   1468  1.1.1.4   tron 		LDAP_SUCCESS || e == NULL ) {
   1469  1.1.1.4   tron 		Debug( LDAP_DEBUG_TRACE, "autogroup_modrdn_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
   1470  1.1.1.4   tron 		ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1471  1.1.1.4   tron 		return SLAP_CB_CONTINUE;
   1472  1.1.1.4   tron 	}
   1473  1.1.1.4   tron 
   1474  1.1.1.4   tron 	/* Must check if a dn is modified */
   1475  1.1.1.4   tron 	for ( age = agi->agi_entry; age ; age = age->age_next ) {
   1476  1.1.1.4   tron 		autogroup_filter_t	*agf;
   1477  1.1.1.4   tron 		for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
   1478  1.1.1.4   tron 			if ( agf->agf_anlist ) {
   1479  1.1.1.4   tron 				if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
   1480  1.1.1.4   tron 					int rc = test_filter( op, e, agf->agf_filter );
   1481  1.1.1.4   tron 					if ( rc == LDAP_COMPARE_TRUE ) {
   1482  1.1.1.4   tron 						age->age_modrdn_olddnmodified = 1;
   1483  1.1.1.4   tron 					}
   1484  1.1.1.4   tron 				}
   1485  1.1.1.4   tron 			}
   1486  1.1.1.4   tron 		}
   1487  1.1.1.4   tron 	}
   1488  1.1.1.4   tron 
   1489  1.1.1.4   tron 	overlay_entry_release_ov( op, e, 0, on );
   1490  1.1.1.4   tron 	ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
   1491  1.1.1.4   tron 	return SLAP_CB_CONTINUE;
   1492  1.1.1.4   tron }
   1493  1.1.1.4   tron 
   1494      1.1  lukem /*
   1495      1.1  lukem ** Builds a filter for searching for the
   1496      1.1  lukem ** group entries, according to the objectClass.
   1497      1.1  lukem */
   1498      1.1  lukem static int
   1499      1.1  lukem autogroup_build_def_filter( autogroup_def_t *agd, Operation *op )
   1500      1.1  lukem {
   1501      1.1  lukem 	char	*ptr;
   1502      1.1  lukem 
   1503      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_build_def_filter\n", 0, 0, 0);
   1504      1.1  lukem 
   1505      1.1  lukem 	op->ors_filterstr.bv_len = STRLENOF( "(=)" )
   1506      1.1  lukem 			+ slap_schema.si_ad_objectClass->ad_cname.bv_len
   1507      1.1  lukem 			+ agd->agd_oc->soc_cname.bv_len;
   1508      1.1  lukem 	ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
   1509      1.1  lukem 	*ptr++ = '(';
   1510      1.1  lukem 	ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
   1511      1.1  lukem 	*ptr++ = '=';
   1512      1.1  lukem 	ptr = lutil_strcopy( ptr, agd->agd_oc->soc_cname.bv_val );
   1513      1.1  lukem 	*ptr++ = ')';
   1514      1.1  lukem 	*ptr = '\0';
   1515      1.1  lukem 
   1516      1.1  lukem 	op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
   1517      1.1  lukem 
   1518      1.1  lukem 	assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );
   1519      1.1  lukem 
   1520      1.1  lukem 	return 0;
   1521      1.1  lukem }
   1522      1.1  lukem 
   1523      1.1  lukem enum {
   1524      1.1  lukem 	AG_ATTRSET = 1,
   1525  1.1.1.4   tron 	AG_MEMBER_OF_AD,
   1526      1.1  lukem 	AG_LAST
   1527      1.1  lukem };
   1528      1.1  lukem 
   1529      1.1  lukem static ConfigDriver	ag_cfgen;
   1530      1.1  lukem 
   1531      1.1  lukem static ConfigTable agcfg[] = {
   1532      1.1  lukem 	{ "autogroup-attrset", "group-oc> <URL-ad> <member-ad",
   1533      1.1  lukem 		3, 4, 0, ARG_MAGIC|AG_ATTRSET, ag_cfgen,
   1534      1.1  lukem 		"( OLcfgCtAt:2.1 NAME 'olcAGattrSet' "
   1535      1.1  lukem 			"DESC 'Automatic groups: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
   1536      1.1  lukem 			"EQUALITY caseIgnoreMatch "
   1537      1.1  lukem 			"SYNTAX OMsDirectoryString "
   1538      1.1  lukem 			"X-ORDERED 'VALUES' )",
   1539      1.1  lukem 			NULL, NULL },
   1540  1.1.1.4   tron 
   1541  1.1.1.4   tron 	{ "autogroup-memberof-ad", "memberOf attribute",
   1542  1.1.1.4   tron 		2, 2, 0, ARG_MAGIC|AG_MEMBER_OF_AD, ag_cfgen,
   1543  1.1.1.4   tron 		"( OLcfgCtAt:2.2 NAME 'olcAGmemberOfAd' "
   1544  1.1.1.4   tron 			"DESC 'memberOf attribute' "
   1545  1.1.1.4   tron 			"SYNTAX OMsDirectoryString SINGLE-VALUE )",
   1546  1.1.1.4   tron 			NULL, NULL },
   1547  1.1.1.4   tron 
   1548      1.1  lukem 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
   1549      1.1  lukem };
   1550      1.1  lukem 
   1551      1.1  lukem static ConfigOCs agocs[] = {
   1552      1.1  lukem 	{ "( OLcfgCtOc:2.1 "
   1553      1.1  lukem 		"NAME 'olcAutomaticGroups' "
   1554      1.1  lukem 		"DESC 'Automatic groups configuration' "
   1555      1.1  lukem 		"SUP olcOverlayConfig "
   1556  1.1.1.4   tron 		"MAY ( "
   1557  1.1.1.4   tron 			"olcAGattrSet "
   1558  1.1.1.4   tron 			"$ olcAGmemberOfAd "
   1559  1.1.1.4   tron 		    ")"
   1560  1.1.1.4   tron 	  ")",
   1561      1.1  lukem 		Cft_Overlay, agcfg, NULL, NULL },
   1562      1.1  lukem 	{ NULL, 0, NULL }
   1563      1.1  lukem };
   1564      1.1  lukem 
   1565      1.1  lukem 
   1566      1.1  lukem static int
   1567      1.1  lukem ag_cfgen( ConfigArgs *c )
   1568      1.1  lukem {
   1569      1.1  lukem 	slap_overinst		*on = (slap_overinst *)c->bi;
   1570      1.1  lukem 	autogroup_info_t		*agi = (autogroup_info_t *)on->on_bi.bi_private;
   1571      1.1  lukem 	autogroup_def_t		*agd;
   1572      1.1  lukem 	autogroup_entry_t	*age;
   1573      1.1  lukem 
   1574      1.1  lukem 	int rc = 0, i;
   1575      1.1  lukem 
   1576      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_cfgen\n", 0, 0, 0);
   1577      1.1  lukem 
   1578      1.1  lukem 	if( agi == NULL ) {
   1579      1.1  lukem 		agi = (autogroup_info_t*)ch_calloc( 1, sizeof(autogroup_info_t) );
   1580      1.1  lukem 		ldap_pvt_thread_mutex_init( &agi->agi_mutex );
   1581      1.1  lukem 		agi->agi_def = NULL;
   1582      1.1  lukem 		agi->agi_entry = NULL;
   1583      1.1  lukem 		on->on_bi.bi_private = (void *)agi;
   1584      1.1  lukem 	}
   1585      1.1  lukem 
   1586      1.1  lukem 	agd = agi->agi_def;
   1587      1.1  lukem 	age = agi->agi_entry;
   1588      1.1  lukem 
   1589      1.1  lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
   1590      1.1  lukem 
   1591  1.1.1.4   tron 		switch( c->type ){
   1592  1.1.1.4   tron 		case AG_ATTRSET:
   1593  1.1.1.4   tron 			for ( i = 0 ; agd ; i++, agd = agd->agd_next ) {
   1594  1.1.1.4   tron 				struct berval	bv;
   1595  1.1.1.4   tron 				char		*ptr = c->cr_msg;
   1596  1.1.1.4   tron 
   1597  1.1.1.4   tron 				assert(agd->agd_oc != NULL);
   1598  1.1.1.4   tron 				assert(agd->agd_member_url_ad != NULL);
   1599  1.1.1.4   tron 				assert(agd->agd_member_ad != NULL);
   1600  1.1.1.4   tron 
   1601  1.1.1.4   tron 				ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1602  1.1.1.4   tron 					SLAP_X_ORDERED_FMT "%s %s %s", i,
   1603  1.1.1.4   tron 					agd->agd_oc->soc_cname.bv_val,
   1604  1.1.1.4   tron 					agd->agd_member_url_ad->ad_cname.bv_val,
   1605  1.1.1.4   tron 					agd->agd_member_ad->ad_cname.bv_val );
   1606  1.1.1.4   tron 
   1607  1.1.1.4   tron 				bv.bv_val = c->cr_msg;
   1608  1.1.1.4   tron 				bv.bv_len = ptr - bv.bv_val;
   1609  1.1.1.4   tron 				value_add_one ( &c->rvalue_vals, &bv );
   1610  1.1.1.4   tron 
   1611  1.1.1.4   tron 			}
   1612  1.1.1.4   tron 			break;
   1613  1.1.1.4   tron 
   1614  1.1.1.4   tron 		case AG_MEMBER_OF_AD:
   1615  1.1.1.4   tron 			if ( agi->agi_memberof_ad != NULL ){
   1616  1.1.1.4   tron 				value_add_one( &c->rvalue_vals, &agi->agi_memberof_ad->ad_cname );
   1617  1.1.1.4   tron 			}
   1618  1.1.1.4   tron 			break;
   1619      1.1  lukem 
   1620  1.1.1.4   tron 		default:
   1621  1.1.1.4   tron 			assert( 0 );
   1622  1.1.1.4   tron 			return 1;
   1623  1.1.1.4   tron       }
   1624      1.1  lukem 
   1625      1.1  lukem 		return rc;
   1626      1.1  lukem 
   1627      1.1  lukem 	}else if ( c->op == LDAP_MOD_DELETE ) {
   1628      1.1  lukem 		if ( c->valx < 0) {
   1629      1.1  lukem 			autogroup_def_t 		*agd_next;
   1630      1.1  lukem 			autogroup_entry_t	*age_next;
   1631      1.1  lukem 			autogroup_filter_t	*agf = age->age_filter,
   1632      1.1  lukem 						*agf_next;
   1633      1.1  lukem 
   1634      1.1  lukem 			for ( agd_next = agd; agd_next; agd = agd_next ) {
   1635      1.1  lukem 				agd_next = agd->agd_next;
   1636      1.1  lukem 
   1637      1.1  lukem 				ch_free( agd );
   1638      1.1  lukem 			}
   1639      1.1  lukem 
   1640      1.1  lukem 			for ( age_next = age ; age_next ; age = age_next ) {
   1641      1.1  lukem 				age_next = age->age_next;
   1642      1.1  lukem 
   1643      1.1  lukem 				ch_free( age->age_dn.bv_val );
   1644      1.1  lukem 				ch_free( age->age_ndn.bv_val );
   1645      1.1  lukem 
   1646      1.1  lukem 				for( agf_next = agf ; agf_next ; agf = agf_next ){
   1647      1.1  lukem 					agf_next = agf->agf_next;
   1648      1.1  lukem 
   1649      1.1  lukem 					filter_free( agf->agf_filter );
   1650      1.1  lukem 					ch_free( agf->agf_filterstr.bv_val );
   1651      1.1  lukem 					ch_free( agf->agf_dn.bv_val );
   1652      1.1  lukem 					ch_free( agf->agf_ndn.bv_val );
   1653  1.1.1.4   tron 					anlist_free( agf->agf_anlist, 1, NULL );
   1654  1.1.1.4   tron 					ch_free( agf );
   1655      1.1  lukem 				}
   1656      1.1  lukem 
   1657      1.1  lukem 				ldap_pvt_thread_mutex_init( &age->age_mutex );
   1658      1.1  lukem 				ch_free( age );
   1659      1.1  lukem 			}
   1660      1.1  lukem 
   1661      1.1  lukem 			ch_free( agi );
   1662      1.1  lukem 			on->on_bi.bi_private = NULL;
   1663      1.1  lukem 
   1664      1.1  lukem 		} else {
   1665      1.1  lukem 			autogroup_def_t		**agdp;
   1666      1.1  lukem 			autogroup_entry_t	*age_next, *age_prev;
   1667      1.1  lukem 			autogroup_filter_t	*agf,
   1668      1.1  lukem 						*agf_next;
   1669      1.1  lukem 
   1670      1.1  lukem 			for ( i = 0, agdp = &agi->agi_def;
   1671      1.1  lukem 				i < c->valx; i++ )
   1672      1.1  lukem 			{
   1673      1.1  lukem 				if ( *agdp == NULL) {
   1674      1.1  lukem 					return 1;
   1675      1.1  lukem 				}
   1676      1.1  lukem 				agdp = &(*agdp)->agd_next;
   1677      1.1  lukem 			}
   1678      1.1  lukem 
   1679      1.1  lukem 			agd = *agdp;
   1680      1.1  lukem 			*agdp = agd->agd_next;
   1681      1.1  lukem 
   1682      1.1  lukem 			for ( age_next = age , age_prev = NULL ; age_next ; age_prev = age, age = age_next ) {
   1683      1.1  lukem 				age_next = age->age_next;
   1684      1.1  lukem 
   1685      1.1  lukem 				if( age->age_def == agd ) {
   1686      1.1  lukem 					agf = age->age_filter;
   1687      1.1  lukem 
   1688      1.1  lukem 					ch_free( age->age_dn.bv_val );
   1689      1.1  lukem 					ch_free( age->age_ndn.bv_val );
   1690      1.1  lukem 
   1691      1.1  lukem 					for ( agf_next = agf; agf_next ; agf = agf_next ) {
   1692      1.1  lukem 						agf_next = agf->agf_next;
   1693      1.1  lukem 						filter_free( agf->agf_filter );
   1694      1.1  lukem 						ch_free( agf->agf_filterstr.bv_val );
   1695      1.1  lukem 						ch_free( agf->agf_dn.bv_val );
   1696      1.1  lukem 						ch_free( agf->agf_ndn.bv_val );
   1697  1.1.1.4   tron 						anlist_free( agf->agf_anlist, 1, NULL );
   1698  1.1.1.4   tron 						ch_free( agf );
   1699      1.1  lukem 					}
   1700      1.1  lukem 
   1701      1.1  lukem 					ldap_pvt_thread_mutex_destroy( &age->age_mutex );
   1702      1.1  lukem 					ch_free( age );
   1703      1.1  lukem 
   1704      1.1  lukem 					age = age_prev;
   1705      1.1  lukem 
   1706      1.1  lukem 					if( age_prev != NULL ) {
   1707      1.1  lukem 						age_prev->age_next = age_next;
   1708      1.1  lukem 					}
   1709      1.1  lukem 				}
   1710      1.1  lukem 			}
   1711      1.1  lukem 
   1712      1.1  lukem 			ch_free( agd );
   1713      1.1  lukem 			agd = agi->agi_def;
   1714      1.1  lukem 
   1715      1.1  lukem 		}
   1716      1.1  lukem 
   1717      1.1  lukem 		return rc;
   1718      1.1  lukem 	}
   1719      1.1  lukem 
   1720      1.1  lukem 	switch(c->type){
   1721      1.1  lukem 	case AG_ATTRSET: {
   1722      1.1  lukem 		autogroup_def_t		**agdp,
   1723      1.1  lukem 					*agd_next = NULL;
   1724      1.1  lukem 		ObjectClass		*oc = NULL;
   1725      1.1  lukem 		AttributeDescription	*member_url_ad = NULL,
   1726      1.1  lukem 					*member_ad = NULL;
   1727      1.1  lukem 		const char		*text;
   1728      1.1  lukem 
   1729      1.1  lukem 
   1730      1.1  lukem 		oc = oc_find( c->argv[ 1 ] );
   1731      1.1  lukem 		if( oc == NULL ){
   1732      1.1  lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1733      1.1  lukem 				"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
   1734      1.1  lukem 				"unable to find ObjectClass \"%s\"",
   1735      1.1  lukem 				c->argv[ 1 ] );
   1736      1.1  lukem 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1737      1.1  lukem 				c->log, c->cr_msg, 0 );
   1738      1.1  lukem 			return 1;
   1739      1.1  lukem 		}
   1740      1.1  lukem 
   1741      1.1  lukem 
   1742      1.1  lukem 		rc = slap_str2ad( c->argv[ 2 ], &member_url_ad, &text );
   1743      1.1  lukem 		if( rc != LDAP_SUCCESS ) {
   1744      1.1  lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1745      1.1  lukem 				"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
   1746      1.1  lukem 				"unable to find AttributeDescription \"%s\"",
   1747      1.1  lukem 				c->argv[ 2 ] );
   1748      1.1  lukem 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1749      1.1  lukem 				c->log, c->cr_msg, 0 );
   1750      1.1  lukem 			return 1;
   1751      1.1  lukem 		}
   1752      1.1  lukem 
   1753      1.1  lukem 		if( !is_at_subtype( member_url_ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
   1754      1.1  lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1755      1.1  lukem 				"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
   1756      1.1  lukem 				"AttributeDescription \"%s\" ",
   1757      1.1  lukem 				"must be of a subtype \"labeledURI\"",
   1758      1.1  lukem 				c->argv[ 2 ] );
   1759      1.1  lukem 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1760      1.1  lukem 				c->log, c->cr_msg, 0 );
   1761      1.1  lukem 			return 1;
   1762      1.1  lukem 		}
   1763      1.1  lukem 
   1764      1.1  lukem 		rc = slap_str2ad( c->argv[3], &member_ad, &text );
   1765      1.1  lukem 		if( rc != LDAP_SUCCESS ) {
   1766      1.1  lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1767      1.1  lukem 				"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
   1768      1.1  lukem 				"unable to find AttributeDescription \"%s\"",
   1769      1.1  lukem 				c->argv[ 3 ] );
   1770      1.1  lukem 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1771      1.1  lukem 				c->log, c->cr_msg, 0 );
   1772      1.1  lukem 			return 1;
   1773      1.1  lukem 		}
   1774      1.1  lukem 
   1775      1.1  lukem 		for ( agdp = &agi->agi_def ; *agdp ; agdp = &(*agdp)->agd_next ) {
   1776      1.1  lukem 			/* The same URL attribute / member attribute pair
   1777      1.1  lukem 			* cannot be repeated */
   1778      1.1  lukem 
   1779      1.1  lukem 			if ( (*agdp)->agd_member_url_ad == member_url_ad && (*agdp)->agd_member_ad == member_ad ) {
   1780      1.1  lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1781      1.1  lukem 					"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
   1782      1.1  lukem 					"URL attributeDescription \"%s\" already mapped",
   1783      1.1  lukem 					member_ad->ad_cname.bv_val );
   1784      1.1  lukem 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1785      1.1  lukem 					c->log, c->cr_msg, 0 );
   1786      1.1  lukem /*				return 1; //warning*/
   1787      1.1  lukem 			}
   1788      1.1  lukem 		}
   1789      1.1  lukem 
   1790      1.1  lukem 		if ( c->valx > 0 ) {
   1791      1.1  lukem 			int	i;
   1792      1.1  lukem 
   1793      1.1  lukem 			for ( i = 0, agdp = &agi->agi_def ;
   1794      1.1  lukem 				i < c->valx; i++ )
   1795      1.1  lukem 			{
   1796      1.1  lukem 				if ( *agdp == NULL ) {
   1797      1.1  lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1798      1.1  lukem 						"\"autogroup-attrset <oc> <URL-ad> <member-ad>\": "
   1799      1.1  lukem 						"invalid index {%d}",
   1800      1.1  lukem 						c->valx );
   1801      1.1  lukem 					Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1802      1.1  lukem 						c->log, c->cr_msg, 0 );
   1803      1.1  lukem 
   1804      1.1  lukem 					return 1;
   1805      1.1  lukem 				}
   1806      1.1  lukem 				agdp = &(*agdp)->agd_next;
   1807      1.1  lukem 			}
   1808      1.1  lukem 			agd_next = *agdp;
   1809      1.1  lukem 
   1810      1.1  lukem 		} else {
   1811      1.1  lukem 			for ( agdp = &agi->agi_def; *agdp;
   1812      1.1  lukem 				agdp = &(*agdp)->agd_next )
   1813      1.1  lukem 				/* goto last */;
   1814      1.1  lukem 		}
   1815      1.1  lukem 
   1816      1.1  lukem 		*agdp = (autogroup_def_t *)ch_calloc( 1, sizeof(autogroup_info_t));
   1817      1.1  lukem 
   1818      1.1  lukem 		(*agdp)->agd_oc = oc;
   1819      1.1  lukem 		(*agdp)->agd_member_url_ad = member_url_ad;
   1820      1.1  lukem 		(*agdp)->agd_member_ad = member_ad;
   1821      1.1  lukem 		(*agdp)->agd_next = agd_next;
   1822      1.1  lukem 
   1823  1.1.1.4   tron 		} break;
   1824  1.1.1.4   tron 
   1825  1.1.1.4   tron 	case AG_MEMBER_OF_AD: {
   1826  1.1.1.4   tron 		AttributeDescription *memberof_ad = NULL;
   1827  1.1.1.4   tron 		const char     *text;
   1828  1.1.1.4   tron 
   1829  1.1.1.4   tron 		rc = slap_str2ad( c->argv[ 1 ], &memberof_ad, &text );
   1830  1.1.1.4   tron 		if( rc != LDAP_SUCCESS ) {
   1831  1.1.1.4   tron 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1832  1.1.1.4   tron 				"\"autogroup-memberof-ad <memberof-ad>\": "
   1833  1.1.1.4   tron 				"unable to find AttributeDescription \"%s\"",
   1834  1.1.1.4   tron 				c->argv[ 1 ] );
   1835  1.1.1.4   tron 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1836  1.1.1.4   tron 				c->log, c->cr_msg, 0 );
   1837  1.1.1.4   tron 			return 1;
   1838  1.1.1.4   tron 		}
   1839  1.1.1.4   tron 
   1840  1.1.1.4   tron 		if ( !is_at_syntax( memberof_ad->ad_type, SLAPD_DN_SYNTAX )    /* e.g. "member" */
   1841  1.1.1.4   tron 		     && !is_at_syntax( memberof_ad->ad_type, SLAPD_NAMEUID_SYNTAX ) )  /* e.g. "uniqueMember" */
   1842  1.1.1.4   tron 		{
   1843  1.1.1.4   tron 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1844  1.1.1.4   tron 				"memberof attribute=\"%s\" must either "
   1845  1.1.1.4   tron 				"have DN (%s) or nameUID (%s) syntax",
   1846  1.1.1.4   tron 				c->argv[ 1 ], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
   1847  1.1.1.4   tron 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
   1848  1.1.1.4   tron 				c->log, c->cr_msg, 0 );
   1849  1.1.1.4   tron 			return 1;
   1850  1.1.1.4   tron 		}
   1851  1.1.1.4   tron 
   1852  1.1.1.4   tron 		agi->agi_memberof_ad = memberof_ad;
   1853      1.1  lukem 
   1854      1.1  lukem 		} break;
   1855      1.1  lukem 
   1856      1.1  lukem 	default:
   1857      1.1  lukem 		rc = 1;
   1858      1.1  lukem 		break;
   1859      1.1  lukem 	}
   1860      1.1  lukem 
   1861      1.1  lukem 	return rc;
   1862      1.1  lukem }
   1863      1.1  lukem 
   1864  1.1.1.4   tron extern int slapMode;
   1865  1.1.1.4   tron 
   1866      1.1  lukem /*
   1867      1.1  lukem ** Do a search for all the groups in the
   1868      1.1  lukem ** database, and add them to out internal list.
   1869      1.1  lukem */
   1870      1.1  lukem static int
   1871      1.1  lukem autogroup_db_open(
   1872      1.1  lukem 	BackendDB	*be,
   1873      1.1  lukem 	ConfigReply	*cr )
   1874      1.1  lukem {
   1875  1.1.1.2  lukem 	slap_overinst			*on = (slap_overinst *) be->bd_info;
   1876      1.1  lukem 	autogroup_info_t		*agi = on->on_bi.bi_private;
   1877      1.1  lukem 	autogroup_def_t		*agd;
   1878      1.1  lukem 	autogroup_sc_t		ags;
   1879      1.1  lukem 	Operation		*op;
   1880      1.1  lukem 	slap_callback		cb = { 0 };
   1881      1.1  lukem 
   1882      1.1  lukem 	void				*thrctx = ldap_pvt_thread_pool_context();
   1883      1.1  lukem 	Connection			conn = { 0 };
   1884      1.1  lukem 	OperationBuffer 	opbuf;
   1885      1.1  lukem 
   1886      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_open\n", 0, 0, 0);
   1887      1.1  lukem 
   1888  1.1.1.4   tron 	if ( agi == NULL || !( slapMode & SLAP_SERVER_MODE )) {
   1889  1.1.1.2  lukem 		return 0;
   1890  1.1.1.2  lukem 	}
   1891  1.1.1.2  lukem 
   1892      1.1  lukem 	connection_fake_init( &conn, &opbuf, thrctx );
   1893      1.1  lukem 	op = &opbuf.ob_op;
   1894      1.1  lukem 
   1895      1.1  lukem 	op->ors_attrsonly = 0;
   1896      1.1  lukem 	op->o_tag = LDAP_REQ_SEARCH;
   1897      1.1  lukem 	op->o_dn = be->be_rootdn;
   1898      1.1  lukem 	op->o_ndn = be->be_rootndn;
   1899      1.1  lukem 
   1900      1.1  lukem 	op->o_req_dn = be->be_suffix[0];
   1901      1.1  lukem 	op->o_req_ndn = be->be_nsuffix[0];
   1902      1.1  lukem 
   1903      1.1  lukem 	op->ors_scope = LDAP_SCOPE_SUBTREE;
   1904      1.1  lukem 	op->ors_deref = LDAP_DEREF_NEVER;
   1905      1.1  lukem 	op->ors_limit = NULL;
   1906      1.1  lukem 	op->ors_tlimit = SLAP_NO_LIMIT;
   1907      1.1  lukem 	op->ors_slimit = SLAP_NO_LIMIT;
   1908      1.1  lukem 	op->ors_attrs =  slap_anlist_no_attrs;
   1909      1.1  lukem 
   1910  1.1.1.2  lukem 	op->o_bd = be;
   1911  1.1.1.2  lukem 	op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1912  1.1.1.2  lukem 
   1913  1.1.1.2  lukem 	ags.ags_info = agi;
   1914  1.1.1.2  lukem 	cb.sc_private = &ags;
   1915  1.1.1.2  lukem 	cb.sc_response = autogroup_group_add_cb;
   1916  1.1.1.2  lukem 	cb.sc_cleanup = NULL;
   1917  1.1.1.2  lukem 	cb.sc_next = NULL;
   1918  1.1.1.2  lukem 
   1919  1.1.1.2  lukem 	op->o_callback = &cb;
   1920      1.1  lukem 
   1921      1.1  lukem 	for (agd = agi->agi_def ; agd ; agd = agd->agd_next) {
   1922  1.1.1.4   tron 		SlapReply	rs = { REP_RESULT };
   1923      1.1  lukem 
   1924      1.1  lukem 		autogroup_build_def_filter(agd, op);
   1925      1.1  lukem 
   1926      1.1  lukem 		ags.ags_def = agd;
   1927      1.1  lukem 
   1928      1.1  lukem 		op->o_bd->be_search( op, &rs );
   1929      1.1  lukem 
   1930  1.1.1.2  lukem 		filter_free_x( op, op->ors_filter, 1 );
   1931      1.1  lukem 		op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
   1932      1.1  lukem 	}
   1933      1.1  lukem 
   1934  1.1.1.4   tron 	if( ! agi->agi_memberof_ad ){
   1935  1.1.1.4   tron 		int			rc;
   1936  1.1.1.4   tron 		const char		*text = NULL;
   1937  1.1.1.4   tron 
   1938  1.1.1.4   tron 		rc = slap_str2ad( SLAPD_MEMBEROF_ATTR, &agi->agi_memberof_ad, &text );
   1939  1.1.1.4   tron 		if ( rc != LDAP_SUCCESS ) {
   1940  1.1.1.4   tron 			Debug( LDAP_DEBUG_ANY, "autogroup_db_open: "
   1941  1.1.1.4   tron 			"unable to find attribute=\"%s\": %s (%d)\n",
   1942  1.1.1.4   tron 			SLAPD_MEMBEROF_ATTR, text, rc );
   1943  1.1.1.4   tron 			return rc;
   1944  1.1.1.4   tron 		}
   1945  1.1.1.4   tron 	}
   1946  1.1.1.4   tron 
   1947      1.1  lukem 	return 0;
   1948      1.1  lukem }
   1949      1.1  lukem 
   1950      1.1  lukem static int
   1951      1.1  lukem autogroup_db_close(
   1952      1.1  lukem 	BackendDB	*be,
   1953      1.1  lukem 	ConfigReply	*cr )
   1954      1.1  lukem {
   1955      1.1  lukem 	slap_overinst			*on = (slap_overinst *) be->bd_info;
   1956      1.1  lukem 
   1957      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_close\n", 0, 0, 0);
   1958      1.1  lukem 
   1959      1.1  lukem 	if ( on->on_bi.bi_private ) {
   1960      1.1  lukem 		autogroup_info_t		*agi = on->on_bi.bi_private;
   1961      1.1  lukem 		autogroup_entry_t	*age = agi->agi_entry,
   1962      1.1  lukem 					*age_next;
   1963      1.1  lukem 		autogroup_filter_t	*agf, *agf_next;
   1964      1.1  lukem 
   1965      1.1  lukem 		for ( age_next = age; age_next; age = age_next ) {
   1966      1.1  lukem 			age_next = age->age_next;
   1967      1.1  lukem 
   1968      1.1  lukem 			ch_free( age->age_dn.bv_val );
   1969      1.1  lukem 			ch_free( age->age_ndn.bv_val );
   1970      1.1  lukem 
   1971      1.1  lukem 			agf = age->age_filter;
   1972      1.1  lukem 
   1973      1.1  lukem 			for ( agf_next = agf; agf_next; agf = agf_next ) {
   1974      1.1  lukem 				agf_next = agf->agf_next;
   1975      1.1  lukem 
   1976      1.1  lukem 				filter_free( agf->agf_filter );
   1977      1.1  lukem 				ch_free( agf->agf_filterstr.bv_val );
   1978      1.1  lukem 				ch_free( agf->agf_dn.bv_val );
   1979      1.1  lukem 				ch_free( agf->agf_ndn.bv_val );
   1980  1.1.1.4   tron 				anlist_free( agf->agf_anlist, 1, NULL );
   1981      1.1  lukem 				ch_free( agf );
   1982      1.1  lukem 			}
   1983      1.1  lukem 
   1984      1.1  lukem 			ldap_pvt_thread_mutex_destroy( &age->age_mutex );
   1985      1.1  lukem 			ch_free( age );
   1986      1.1  lukem 		}
   1987      1.1  lukem 	}
   1988      1.1  lukem 
   1989      1.1  lukem 	return 0;
   1990      1.1  lukem }
   1991      1.1  lukem 
   1992      1.1  lukem static int
   1993      1.1  lukem autogroup_db_destroy(
   1994      1.1  lukem 	BackendDB	*be,
   1995      1.1  lukem 	ConfigReply	*cr )
   1996      1.1  lukem {
   1997      1.1  lukem 	slap_overinst			*on = (slap_overinst *) be->bd_info;
   1998      1.1  lukem 
   1999      1.1  lukem 	Debug( LDAP_DEBUG_TRACE, "==> autogroup_db_destroy\n", 0, 0, 0);
   2000      1.1  lukem 
   2001      1.1  lukem 	if ( on->on_bi.bi_private ) {
   2002      1.1  lukem 		autogroup_info_t		*agi = on->on_bi.bi_private;
   2003      1.1  lukem 		autogroup_def_t		*agd = agi->agi_def,
   2004      1.1  lukem 					*agd_next;
   2005      1.1  lukem 
   2006      1.1  lukem 		for ( agd_next = agd; agd_next; agd = agd_next ) {
   2007      1.1  lukem 			agd_next = agd->agd_next;
   2008      1.1  lukem 
   2009      1.1  lukem 			ch_free( agd );
   2010      1.1  lukem 		}
   2011      1.1  lukem 
   2012      1.1  lukem 		ldap_pvt_thread_mutex_destroy( &agi->agi_mutex );
   2013      1.1  lukem 		ch_free( agi );
   2014      1.1  lukem 	}
   2015      1.1  lukem 
   2016      1.1  lukem 	return 0;
   2017      1.1  lukem }
   2018      1.1  lukem 
   2019      1.1  lukem static slap_overinst	autogroup = { { NULL } };
   2020      1.1  lukem 
   2021      1.1  lukem static
   2022      1.1  lukem int
   2023      1.1  lukem autogroup_initialize(void)
   2024      1.1  lukem {
   2025      1.1  lukem 	int		rc = 0;
   2026      1.1  lukem 	autogroup.on_bi.bi_type = "autogroup";
   2027      1.1  lukem 
   2028      1.1  lukem 	autogroup.on_bi.bi_db_open = autogroup_db_open;
   2029      1.1  lukem 	autogroup.on_bi.bi_db_close = autogroup_db_close;
   2030      1.1  lukem 	autogroup.on_bi.bi_db_destroy = autogroup_db_destroy;
   2031      1.1  lukem 
   2032      1.1  lukem 	autogroup.on_bi.bi_op_add = autogroup_add_entry;
   2033      1.1  lukem 	autogroup.on_bi.bi_op_delete = autogroup_delete_entry;
   2034      1.1  lukem 	autogroup.on_bi.bi_op_modify = autogroup_modify_entry;
   2035  1.1.1.4   tron 	autogroup.on_bi.bi_op_modrdn = autogroup_modrdn_entry;
   2036      1.1  lukem 
   2037      1.1  lukem 	autogroup.on_response = autogroup_response;
   2038      1.1  lukem 
   2039      1.1  lukem 	autogroup.on_bi.bi_cf_ocs = agocs;
   2040      1.1  lukem 
   2041      1.1  lukem 	rc = config_register_schema( agcfg, agocs );
   2042      1.1  lukem 	if ( rc ) {
   2043      1.1  lukem 		return rc;
   2044      1.1  lukem 	}
   2045      1.1  lukem 
   2046      1.1  lukem 	return overlay_register( &autogroup );
   2047      1.1  lukem }
   2048      1.1  lukem 
   2049      1.1  lukem int
   2050      1.1  lukem init_module( int argc, char *argv[] )
   2051      1.1  lukem {
   2052      1.1  lukem 	return autogroup_initialize();
   2053      1.1  lukem }
   2054