mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-07 14:18:15 +08:00
ITS#6536 use the attr part of URIs. from Raphael Ouazana @ Linagora
This commit is contained in:
parent
d2aac4ef22
commit
b0ccdd79fc
@ -3,10 +3,12 @@ autogroup overlay Readme
|
||||
DESCRIPTION
|
||||
The autogroup overlay allows automated updates of group memberships which
|
||||
meet the requirements of any filter contained in the group definition.
|
||||
The filters are built from LDAP URI-valued attributes. Any time an object
|
||||
is added/deleted/updated, it is tested for compliance with the filters,
|
||||
The filters are built from LDAP URI-valued attributes. Any time an object
|
||||
is added/deleted/updated, it is tested for compliance with the filters,
|
||||
and its membership is accordingly updated. For searches and compares
|
||||
it behaves like a static group.
|
||||
If the attribute part of the URI is filled, the group entry is populated
|
||||
by the values of this attribute in the entries resulting from the search.
|
||||
|
||||
BUILDING
|
||||
A Makefile is included.
|
||||
@ -67,6 +69,11 @@ EXAMPLE
|
||||
CAVEATS
|
||||
As with static groups, update operations on groups with a large number
|
||||
of members may be slow.
|
||||
If the attribute part of the URI is specified, modify and delete operations
|
||||
are more difficult to handle. In these cases the overlay will try to detect
|
||||
if groups have been modified and then simply refresh them. This can cause
|
||||
performance hits if the search specified by the URI deals with a significant
|
||||
number of entries.
|
||||
|
||||
ACKNOWLEDGEMENTS
|
||||
This module was originally written in 2007 by Michał Szulczyński.
|
||||
|
@ -38,6 +38,7 @@ typedef struct autogroup_filter_t {
|
||||
struct berval agf_filterstr;
|
||||
Filter *agf_filter;
|
||||
int agf_scope;
|
||||
AttributeName *agf_anlist;
|
||||
struct autogroup_filter_t *agf_next;
|
||||
} autogroup_filter_t;
|
||||
|
||||
@ -56,6 +57,8 @@ typedef struct autogroup_entry_t {
|
||||
autogroup_filter_t *age_filter; /* List of filters made from memberURLs */
|
||||
autogroup_def_t *age_def; /* Attribute definition */
|
||||
ldap_pvt_thread_mutex_t age_mutex;
|
||||
int age_mustrefresh; /* Defined in request to refresh in response */
|
||||
int age_modrdn_olddnmodified; /* Defined in request to refresh in response */
|
||||
struct autogroup_entry_t *age_next;
|
||||
} autogroup_entry_t;
|
||||
|
||||
@ -75,6 +78,7 @@ typedef struct autogroup_sc_t {
|
||||
/* Used for adding members, found when searching, to a group. */
|
||||
typedef struct autogroup_ga_t {
|
||||
autogroup_entry_t *agg_group; /* The group to which the members will be added. */
|
||||
autogroup_filter_t *agg_filter; /* Current filter */
|
||||
Entry *agg_entry; /* Used in autogroup_member_search_cb to modify
|
||||
this entry with the search results. */
|
||||
|
||||
@ -94,9 +98,9 @@ static int
|
||||
autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
Modifications modlist;
|
||||
Modifications *modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
|
||||
SlapReply sreply = {REP_RESULT};
|
||||
BerValue vals[ 2 ], nvals[ 2 ];
|
||||
BerValue *vals, *nvals;
|
||||
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
|
||||
Operation o = *op;
|
||||
|
||||
@ -106,17 +110,71 @@ autogroup_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, autog
|
||||
assert( dn != NULL );
|
||||
assert( ndn != NULL );
|
||||
|
||||
vals[ 0 ] = *dn;
|
||||
vals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
|
||||
nvals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
|
||||
ber_dupbv( vals, dn );
|
||||
BER_BVZERO( &vals[ 1 ] );
|
||||
nvals[ 0 ] = *ndn;
|
||||
ber_dupbv( nvals, ndn );
|
||||
BER_BVZERO( &nvals[ 1 ] );
|
||||
|
||||
modlist->sml_op = LDAP_MOD_ADD;
|
||||
modlist->sml_desc = age->age_def->agd_member_ad;
|
||||
modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
|
||||
modlist->sml_values = vals;
|
||||
modlist->sml_nvalues = nvals;
|
||||
modlist->sml_numvals = 1;
|
||||
modlist->sml_flags = SLAP_MOD_INTERNAL;
|
||||
modlist->sml_next = NULL;
|
||||
|
||||
o.o_tag = LDAP_REQ_MODIFY;
|
||||
o.o_callback = &cb;
|
||||
o.orm_modlist = modlist;
|
||||
o.o_req_dn = age->age_dn;
|
||||
o.o_req_ndn = age->age_ndn;
|
||||
o.o_permissive_modify = 1;
|
||||
o.o_managedsait = SLAP_CONTROL_CRITICAL;
|
||||
o.o_relax = SLAP_CONTROL_CRITICAL;
|
||||
|
||||
o.o_bd->bd_info = (BackendInfo *)on->on_info;
|
||||
(void)op->o_bd->be_modify( &o, &sreply );
|
||||
o.o_bd->bd_info = (BackendInfo *)on;
|
||||
|
||||
slap_mods_free( modlist, 1 );
|
||||
|
||||
return sreply.sr_err;
|
||||
}
|
||||
|
||||
/*
|
||||
** e - the entry where to get the attribute values
|
||||
** age - the group to which the values will be added
|
||||
*/
|
||||
static int
|
||||
autogroup_add_member_values_to_group( Operation *op, Entry *e, autogroup_entry_t *age, AttributeDescription *attrdesc )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
Modifications modlist;
|
||||
SlapReply sreply = {REP_RESULT};
|
||||
Attribute *attr;
|
||||
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
|
||||
Operation o = *op;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_values_to_group adding <%s> to <%s>\n",
|
||||
e->e_name.bv_val, age->age_dn.bv_val, 0);
|
||||
|
||||
assert( e != NULL );
|
||||
|
||||
attr = attrs_find( e->e_attrs, attrdesc );
|
||||
if (!attr) {
|
||||
// Nothing to add
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
modlist.sml_op = LDAP_MOD_ADD;
|
||||
modlist.sml_desc = age->age_def->agd_member_ad;
|
||||
modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
|
||||
modlist.sml_values = vals;
|
||||
modlist.sml_nvalues = nvals;
|
||||
modlist.sml_numvals = 1;
|
||||
modlist.sml_values = attr->a_vals;
|
||||
modlist.sml_nvalues = attr->a_nvals;
|
||||
modlist.sml_numvals = attr->a_numvals;
|
||||
modlist.sml_flags = SLAP_MOD_INTERNAL;
|
||||
modlist.sml_next = NULL;
|
||||
|
||||
@ -145,9 +203,9 @@ static int
|
||||
autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, autogroup_entry_t *age )
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
Modifications modlist;
|
||||
Modifications *modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
|
||||
SlapReply sreply = {REP_RESULT};
|
||||
BerValue vals[ 2 ], nvals[ 2 ];
|
||||
BerValue *vals, *nvals;
|
||||
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
|
||||
Operation o = *op;
|
||||
|
||||
@ -155,33 +213,35 @@ autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn,
|
||||
Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing all members from <%s>\n",
|
||||
age->age_dn.bv_val, 0 ,0);
|
||||
|
||||
modlist.sml_values = NULL;
|
||||
modlist.sml_nvalues = NULL;
|
||||
modlist.sml_numvals = 0;
|
||||
modlist->sml_values = NULL;
|
||||
modlist->sml_nvalues = NULL;
|
||||
modlist->sml_numvals = 0;
|
||||
} else {
|
||||
Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing <%s> from <%s>\n",
|
||||
dn->bv_val, age->age_dn.bv_val, 0);
|
||||
|
||||
vals[ 0 ] = *dn;
|
||||
vals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
|
||||
nvals = (BerValue *)ch_calloc( 2, sizeof( BerValue ) );
|
||||
ber_dupbv( vals, dn );
|
||||
BER_BVZERO( &vals[ 1 ] );
|
||||
nvals[ 0 ] = *ndn;
|
||||
ber_dupbv( nvals, ndn );
|
||||
BER_BVZERO( &nvals[ 1 ] );
|
||||
|
||||
modlist.sml_values = vals;
|
||||
modlist.sml_nvalues = nvals;
|
||||
modlist.sml_numvals = 1;
|
||||
modlist->sml_values = vals;
|
||||
modlist->sml_nvalues = nvals;
|
||||
modlist->sml_numvals = 1;
|
||||
}
|
||||
|
||||
|
||||
modlist.sml_op = LDAP_MOD_DELETE;
|
||||
modlist.sml_desc = age->age_def->agd_member_ad;
|
||||
modlist.sml_type = age->age_def->agd_member_ad->ad_cname;
|
||||
modlist.sml_flags = SLAP_MOD_INTERNAL;
|
||||
modlist.sml_next = NULL;
|
||||
modlist->sml_op = LDAP_MOD_DELETE;
|
||||
modlist->sml_desc = age->age_def->agd_member_ad;
|
||||
modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
|
||||
modlist->sml_flags = SLAP_MOD_INTERNAL;
|
||||
modlist->sml_next = NULL;
|
||||
|
||||
o.o_callback = &cb;
|
||||
o.o_tag = LDAP_REQ_MODIFY;
|
||||
o.orm_modlist = &modlist;
|
||||
o.orm_modlist = modlist;
|
||||
o.o_req_dn = age->age_dn;
|
||||
o.o_req_ndn = age->age_ndn;
|
||||
o.o_relax = SLAP_CONTROL_CRITICAL;
|
||||
@ -192,6 +252,8 @@ autogroup_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn,
|
||||
(void)op->o_bd->be_modify( &o, &sreply );
|
||||
o.o_bd->bd_info = (BackendInfo *)on;
|
||||
|
||||
slap_mods_free( modlist, 1 );
|
||||
|
||||
return sreply.sr_err;
|
||||
}
|
||||
|
||||
@ -209,25 +271,43 @@ autogroup_member_search_cb( Operation *op, SlapReply *rs )
|
||||
if ( rs->sr_type == REP_SEARCH ) {
|
||||
autogroup_ga_t *agg = (autogroup_ga_t *)op->o_callback->sc_private;
|
||||
autogroup_entry_t *age = agg->agg_group;
|
||||
autogroup_filter_t *agf = agg->agg_filter;
|
||||
Modification mod;
|
||||
const char *text = NULL;
|
||||
char textbuf[1024];
|
||||
struct berval vals[ 2 ], nvals[ 2 ];
|
||||
struct berval *vals, *nvals;
|
||||
int numvals;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_cb <%s>\n",
|
||||
rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
|
||||
|
||||
vals[ 0 ] = rs->sr_entry->e_name;
|
||||
BER_BVZERO( &vals[ 1 ] );
|
||||
nvals[ 0 ] = rs->sr_entry->e_nname;
|
||||
BER_BVZERO( &nvals[ 1 ] );
|
||||
if ( agf->agf_anlist ) {
|
||||
Attribute *attr = attrs_find( rs->sr_entry->e_attrs, agf->agf_anlist[0].an_desc );
|
||||
if (attr) {
|
||||
vals = attr->a_vals;
|
||||
nvals = attr->a_nvals;
|
||||
numvals = attr->a_numvals;
|
||||
} else {
|
||||
// Nothing to add
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
struct berval lvals[ 2 ], lnvals[ 2 ];
|
||||
lvals[ 0 ] = rs->sr_entry->e_name;
|
||||
BER_BVZERO( &lvals[ 1 ] );
|
||||
lnvals[ 0 ] = rs->sr_entry->e_nname;
|
||||
BER_BVZERO( &lnvals[ 1 ] );
|
||||
vals = lvals;
|
||||
nvals = lnvals;
|
||||
numvals = 1;
|
||||
}
|
||||
|
||||
mod.sm_op = LDAP_MOD_ADD;
|
||||
mod.sm_desc = age->age_def->agd_member_ad;
|
||||
mod.sm_type = age->age_def->agd_member_ad->ad_cname;
|
||||
mod.sm_values = vals;
|
||||
mod.sm_nvalues = nvals;
|
||||
mod.sm_numvals = 1;
|
||||
mod.sm_numvals = numvals;
|
||||
|
||||
modify_add_values( agg->agg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
|
||||
}
|
||||
@ -249,36 +329,56 @@ autogroup_member_search_modify_cb( Operation *op, SlapReply *rs )
|
||||
if ( rs->sr_type == REP_SEARCH ) {
|
||||
autogroup_ga_t *agg = (autogroup_ga_t *)op->o_callback->sc_private;
|
||||
autogroup_entry_t *age = agg->agg_group;
|
||||
autogroup_filter_t *agf = agg->agg_filter;
|
||||
Modifications *modlist;
|
||||
struct berval vals[ 2 ], nvals[ 2 ];
|
||||
struct berval *vals, *nvals;
|
||||
int numvals;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "==> autogroup_member_search_modify_cb <%s>\n",
|
||||
rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
|
||||
|
||||
vals[ 0 ] = rs->sr_entry->e_name;
|
||||
BER_BVZERO( &vals[ 1 ] );
|
||||
nvals[ 0 ] = rs->sr_entry->e_nname;
|
||||
BER_BVZERO( &nvals[ 1 ] );
|
||||
|
||||
modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
|
||||
|
||||
modlist->sml_op = LDAP_MOD_ADD;
|
||||
modlist->sml_desc = age->age_def->agd_member_ad;
|
||||
modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
|
||||
|
||||
ber_bvarray_dup_x( &modlist->sml_values, vals, NULL );
|
||||
ber_bvarray_dup_x( &modlist->sml_nvalues, nvals, NULL );
|
||||
modlist->sml_numvals = 1;
|
||||
|
||||
modlist->sml_flags = SLAP_MOD_INTERNAL;
|
||||
modlist->sml_next = NULL;
|
||||
|
||||
if ( agg->agg_mod == NULL ) {
|
||||
agg->agg_mod = modlist;
|
||||
agg->agg_mod_last = modlist;
|
||||
if ( agf->agf_anlist ) {
|
||||
Attribute *attr = attrs_find( rs->sr_entry->e_attrs, agf->agf_anlist[0].an_desc );
|
||||
if (attr) {
|
||||
vals = attr->a_vals;
|
||||
nvals = attr->a_nvals;
|
||||
numvals = attr->a_numvals;
|
||||
} else {
|
||||
// Nothing to add
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
agg->agg_mod_last->sml_next = modlist;
|
||||
agg->agg_mod_last = modlist;
|
||||
struct berval lvals[ 2 ], lnvals[ 2 ];
|
||||
lvals[ 0 ] = rs->sr_entry->e_name;
|
||||
BER_BVZERO( &lvals[ 1 ] );
|
||||
lnvals[ 0 ] = rs->sr_entry->e_nname;
|
||||
BER_BVZERO( &lnvals[ 1 ] );
|
||||
vals = lvals;
|
||||
nvals = lnvals;
|
||||
numvals = 1;
|
||||
}
|
||||
|
||||
if ( numvals ) {
|
||||
modlist = (Modifications *)ch_calloc( 1, sizeof( Modifications ) );
|
||||
|
||||
modlist->sml_op = LDAP_MOD_ADD;
|
||||
modlist->sml_desc = age->age_def->agd_member_ad;
|
||||
modlist->sml_type = age->age_def->agd_member_ad->ad_cname;
|
||||
|
||||
ber_bvarray_dup_x( &modlist->sml_values, vals, NULL );
|
||||
ber_bvarray_dup_x( &modlist->sml_nvalues, nvals, NULL );
|
||||
modlist->sml_numvals = numvals;
|
||||
|
||||
modlist->sml_flags = SLAP_MOD_INTERNAL;
|
||||
modlist->sml_next = NULL;
|
||||
|
||||
if ( agg->agg_mod == NULL ) {
|
||||
agg->agg_mod = modlist;
|
||||
agg->agg_mod_last = modlist;
|
||||
} else {
|
||||
agg->agg_mod_last->sml_next = modlist;
|
||||
agg->agg_mod_last = modlist;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -323,9 +423,10 @@ autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *a
|
||||
o.ors_limit = NULL;
|
||||
o.ors_tlimit = SLAP_NO_LIMIT;
|
||||
o.ors_slimit = SLAP_NO_LIMIT;
|
||||
o.ors_attrs = slap_anlist_no_attrs;
|
||||
o.ors_attrs = agf->agf_anlist ? agf->agf_anlist : slap_anlist_no_attrs;
|
||||
|
||||
agg.agg_group = age;
|
||||
agg.agg_filter = agf;
|
||||
agg.agg_mod = NULL;
|
||||
agg.agg_mod_last = NULL;
|
||||
agg.agg_entry = e;
|
||||
@ -346,7 +447,7 @@ autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *a
|
||||
op->o_bd->be_search( &o, &rs );
|
||||
o.o_bd->bd_info = (BackendInfo *)on;
|
||||
|
||||
if ( modify == 1 ) {
|
||||
if ( modify == 1 && agg.agg_mod ) {
|
||||
o = *op;
|
||||
o.o_callback = &null_cb;
|
||||
o.o_tag = LDAP_REQ_MODIFY;
|
||||
@ -417,6 +518,8 @@ autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd,
|
||||
ldap_pvt_thread_mutex_init( &(*agep)->age_mutex );
|
||||
(*agep)->age_def = agd;
|
||||
(*agep)->age_filter = NULL;
|
||||
(*agep)->age_mustrefresh = 0;
|
||||
(*agep)->age_modrdn_olddnmodified = 0;
|
||||
|
||||
ber_dupbv( &(*agep)->age_dn, &e->e_name );
|
||||
ber_dupbv( &(*agep)->age_ndn, &e->e_nname );
|
||||
@ -462,6 +565,33 @@ autogroup_add_group( Operation *op, autogroup_info_t *agi, autogroup_def_t *agd,
|
||||
agf->agf_filter = str2filter( lud->lud_filter );
|
||||
}
|
||||
|
||||
if ( lud->lud_attrs != NULL ) {
|
||||
int i;
|
||||
|
||||
for ( i=0 ; lud->lud_attrs[i]!=NULL ; i++) {
|
||||
/* Just counting */;
|
||||
}
|
||||
|
||||
if ( i > 1 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "autogroup_add_group: to much attributes specified in url <%s>\n",
|
||||
bv->bv_val, 0, 0);
|
||||
/* FIXME: error? */
|
||||
ldap_free_urldesc( lud );
|
||||
ch_free( agf );
|
||||
}
|
||||
|
||||
agf->agf_anlist = str2anlist( NULL, lud->lud_attrs[0], "," );
|
||||
|
||||
if ( agf->agf_anlist == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "autogroup_add_group: unable to find AttributeDescription \"%s\".\n",
|
||||
lud->lud_attrs[0], 0, 0 );
|
||||
/* FIXME: error? */
|
||||
ldap_free_urldesc( lud );
|
||||
ch_free( agf );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
agf->agf_next = NULL;
|
||||
|
||||
|
||||
@ -573,7 +703,11 @@ autogroup_add_entry( Operation *op, SlapReply *rs)
|
||||
if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
|
||||
rc = test_filter( op, op->ora_e, agf->agf_filter );
|
||||
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||
autogroup_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, age );
|
||||
if ( agf->agf_anlist ) {
|
||||
autogroup_add_member_values_to_group( op, op->ora_e, age, agf->agf_anlist[0].an_desc );
|
||||
} else {
|
||||
autogroup_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, age );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -624,6 +758,8 @@ autogroup_delete_group( autogroup_info_t *agi, autogroup_entry_t *e )
|
||||
ch_free( agf->agf_filterstr.bv_val );
|
||||
ch_free( agf->agf_dn.bv_val );
|
||||
ch_free( agf->agf_ndn.bv_val );
|
||||
anlist_free( agf->agf_anlist, 1, NULL );
|
||||
ch_free( agf );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
|
||||
@ -701,7 +837,16 @@ autogroup_delete_entry( Operation *op, SlapReply *rs)
|
||||
if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
|
||||
rc = test_filter( op, e, agf->agf_filter );
|
||||
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||
autogroup_delete_member_from_group( op, &e->e_name, &e->e_nname, age );
|
||||
/* If the attribute is retrieved from the entry, we don't know what to delete
|
||||
** So the group must be entirely refreshed
|
||||
** But the refresh can't be done now because the entry is not deleted
|
||||
** So the group is marked as mustrefresh
|
||||
*/
|
||||
if ( agf->agf_anlist ) {
|
||||
age->age_mustrefresh = 1;
|
||||
} else {
|
||||
autogroup_delete_member_from_group( op, &e->e_name, &e->e_nname, age );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -726,8 +871,33 @@ autogroup_response( Operation *op, SlapReply *rs )
|
||||
BerValue new_dn, new_ndn, pdn;
|
||||
Entry *e, *group;
|
||||
Attribute *a;
|
||||
int is_olddn, is_newdn, dn_equal;
|
||||
int is_olddn, is_newdn, is_value_refresh, dn_equal;
|
||||
|
||||
/* Handle all cases where a refresh of the group is needed */
|
||||
if ( op->o_tag == LDAP_REQ_DELETE || op->o_tag == LDAP_REQ_MODIFY ) {
|
||||
if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op ) ) {
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
|
||||
|
||||
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
|
||||
/* Request detected that the group must be refreshed */
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &age->age_mutex );
|
||||
|
||||
if ( age->age_mustrefresh ) {
|
||||
autogroup_delete_member_from_group( op, NULL, NULL, age) ;
|
||||
|
||||
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
|
||||
autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
|
||||
}
|
||||
}
|
||||
if ( op->o_tag == LDAP_REQ_MODRDN ) {
|
||||
if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
|
||||
|
||||
@ -815,45 +985,68 @@ autogroup_response( Operation *op, SlapReply *rs )
|
||||
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
|
||||
is_olddn = 0;
|
||||
is_newdn = 0;
|
||||
is_value_refresh = 0;
|
||||
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &age->age_mutex );
|
||||
|
||||
if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
|
||||
LDAP_SUCCESS || group == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get group entry <%s>\n", age->age_dn.bv_val, 0, 0);
|
||||
if ( age->age_modrdn_olddnmodified ) {
|
||||
/* Resquest already marked this group to be updated */
|
||||
is_olddn = 1;
|
||||
is_value_refresh = 1;
|
||||
age->age_modrdn_olddnmodified = 0;
|
||||
} else {
|
||||
|
||||
op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
|
||||
op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
|
||||
if ( overlay_entry_get_ov( op, &age->age_ndn, NULL, NULL, 0, &group, on ) !=
|
||||
LDAP_SUCCESS || group == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "autogroup_response MODRDN cannot get group entry <%s>\n", age->age_dn.bv_val, 0, 0);
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
op->o_tmpfree( new_dn.bv_val, op->o_tmpmemctx );
|
||||
op->o_tmpfree( new_ndn.bv_val, op->o_tmpmemctx );
|
||||
|
||||
a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
|
||||
|
||||
if ( a != NULL ) {
|
||||
if ( value_find_ex( age->age_def->agd_member_ad,
|
||||
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
|
||||
a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
|
||||
{
|
||||
is_olddn = 1;
|
||||
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
}
|
||||
a = attrs_find( group->e_attrs, age->age_def->agd_member_ad );
|
||||
|
||||
overlay_entry_release_ov( op, group, 0, on );
|
||||
if ( a != NULL ) {
|
||||
if ( value_find_ex( age->age_def->agd_member_ad,
|
||||
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
|
||||
a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
|
||||
{
|
||||
is_olddn = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
overlay_entry_release_ov( op, group, 0, on );
|
||||
|
||||
}
|
||||
|
||||
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
|
||||
if ( dnIsSuffix( &new_ndn, &agf->agf_ndn ) ) {
|
||||
/* TODO: should retest filter as it could imply conditions on the dn */
|
||||
is_newdn = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( is_value_refresh ) {
|
||||
if ( is_olddn != is_newdn ) {
|
||||
/* group refresh */
|
||||
autogroup_delete_member_from_group( op, NULL, NULL, age) ;
|
||||
|
||||
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
|
||||
autogroup_add_members_from_filter( op, NULL, age, agf, 1 );
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
|
||||
continue;
|
||||
}
|
||||
if ( is_olddn == 1 && is_newdn == 0 ) {
|
||||
autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
|
||||
} else
|
||||
@ -919,7 +1112,7 @@ autogroup_response( Operation *op, SlapReply *rs )
|
||||
|
||||
m = op->orm_modlist;
|
||||
|
||||
for ( ; age ; age = age->age_next ) {
|
||||
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
|
||||
ldap_pvt_thread_mutex_lock( &age->age_mutex );
|
||||
|
||||
dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
|
||||
@ -1000,7 +1193,7 @@ autogroup_response( Operation *op, SlapReply *rs )
|
||||
overlay_entry_release_ov( op, group, 0, on );
|
||||
|
||||
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
|
||||
if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
|
||||
if ( !agf->agf_anlist && dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
|
||||
if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
|
||||
is_newdn = 1;
|
||||
break;
|
||||
@ -1053,6 +1246,26 @@ autogroup_modify_entry( Operation *op, SlapReply *rs)
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
/* Must refresh groups if a matching member value is modified */
|
||||
for ( ; age ; age = age->age_next ) {
|
||||
autogroup_filter_t *agf;
|
||||
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
|
||||
if ( agf->agf_anlist ) {
|
||||
Modifications *m;
|
||||
for ( m = op->orm_modlist ; m ; m = m->sml_next ) {
|
||||
if ( m->sml_desc == agf->agf_anlist[0].an_desc ) {
|
||||
if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
|
||||
int rc = test_filter( op, e, agf->agf_filter );
|
||||
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||
age->age_mustrefresh = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
|
||||
|
||||
if ( a == NULL ) {
|
||||
@ -1075,7 +1288,7 @@ autogroup_modify_entry( Operation *op, SlapReply *rs)
|
||||
|
||||
m = op->orm_modlist;
|
||||
|
||||
for ( ; age ; age = age->age_next ) {
|
||||
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
|
||||
dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &age->age_ndn );
|
||||
|
||||
if ( match == 0 ) {
|
||||
@ -1103,6 +1316,51 @@ autogroup_modify_entry( Operation *op, SlapReply *rs)
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Detect if the olddn is part of a group and so if the group should be refreshed
|
||||
*/
|
||||
static int
|
||||
autogroup_modrdn_entry( Operation *op, SlapReply *rs)
|
||||
{
|
||||
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
|
||||
autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
|
||||
autogroup_entry_t *age = agi->agi_entry;
|
||||
Entry *e;
|
||||
|
||||
if ( get_manageDSAit( op ) ) {
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "==> autogroup_modrdn_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
|
||||
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
|
||||
|
||||
if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
|
||||
LDAP_SUCCESS || e == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "autogroup_modrdn_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
|
||||
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
/* Must check if a dn is modified */
|
||||
for ( ; age ; age = age->age_next ) {
|
||||
autogroup_filter_t *agf;
|
||||
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
|
||||
if ( agf->agf_anlist ) {
|
||||
if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
|
||||
int rc = test_filter( op, e, agf->agf_filter );
|
||||
if ( rc == LDAP_COMPARE_TRUE ) {
|
||||
age->age_modrdn_olddnmodified = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlay_entry_release_ov( op, e, 0, on );
|
||||
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
|
||||
return SLAP_CB_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Builds a filter for searching for the
|
||||
** group entries, according to the objectClass.
|
||||
@ -1240,6 +1498,8 @@ ag_cfgen( ConfigArgs *c )
|
||||
ch_free( agf->agf_filterstr.bv_val );
|
||||
ch_free( agf->agf_dn.bv_val );
|
||||
ch_free( agf->agf_ndn.bv_val );
|
||||
anlist_free( agf->agf_anlist, 1, NULL );
|
||||
ch_free( agf );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_init( &age->age_mutex );
|
||||
@ -1287,6 +1547,8 @@ ag_cfgen( ConfigArgs *c )
|
||||
ch_free( agf->agf_filterstr.bv_val );
|
||||
ch_free( agf->agf_dn.bv_val );
|
||||
ch_free( agf->agf_ndn.bv_val );
|
||||
anlist_free( agf->agf_anlist, 1, NULL );
|
||||
ch_free( agf );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_destroy( &age->age_mutex );
|
||||
@ -1528,6 +1790,7 @@ autogroup_db_close(
|
||||
ch_free( agf->agf_filterstr.bv_val );
|
||||
ch_free( agf->agf_dn.bv_val );
|
||||
ch_free( agf->agf_ndn.bv_val );
|
||||
anlist_free( agf->agf_anlist, 1, NULL );
|
||||
ch_free( agf );
|
||||
}
|
||||
|
||||
@ -1582,6 +1845,7 @@ autogroup_initialize(void)
|
||||
autogroup.on_bi.bi_op_add = autogroup_add_entry;
|
||||
autogroup.on_bi.bi_op_delete = autogroup_delete_entry;
|
||||
autogroup.on_bi.bi_op_modify = autogroup_modify_entry;
|
||||
autogroup.on_bi.bi_op_modrdn = autogroup_modrdn_entry;
|
||||
|
||||
autogroup.on_response = autogroup_response;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user