/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2007-2014 The OpenLDAP Foundation.
+ * Copyright 2007-2018 The OpenLDAP Foundation.
* Portions Copyright 2007 Michał Szulczyński.
* Portions Copyright 2009 Howard Chu.
* All rights reserved.
#define SLAPD_MEMBEROF_ATTR "memberOf"
#endif
+static slap_overinst autogroup;
+
/* Filter represents the memberURL of a group. */
typedef struct autogroup_filter_t {
struct berval agf_dn; /* The base DN in memberURL */
BerValue *vals, *nvals;
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
Operation o = *op;
+ unsigned long opid = op->o_opid;
+ OpExtra oex;
assert( dn != NULL );
assert( ndn != NULL );
modlist->sml_flags = SLAP_MOD_INTERNAL;
modlist->sml_next = NULL;
+ o.o_opid = 0; /* shared with op, saved above */
o.o_tag = LDAP_REQ_MODIFY;
o.o_callback = &cb;
o.orm_modlist = modlist;
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
o.o_req_dn = age->age_dn;
o.o_req_ndn = age->age_ndn;
o.o_permissive_modify = 1;
+ o.o_dont_replicate = 1;
+ o.orm_no_opattrs = 1;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
o.o_relax = SLAP_CONTROL_CRITICAL;
+ oex.oe_key = (void *)&autogroup;
+ LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
+
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &sreply );
o.o_bd->bd_info = (BackendInfo *)on;
+ LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
+
slap_mods_free( modlist, 1 );
+ op->o_opid = opid;
return sreply.sr_err;
}
SlapReply sreply = {REP_RESULT};
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
Operation o = *op;
+ unsigned long opid = op->o_opid;
+ OpExtra oex;
Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_member_values_to_group adding <%s> to <%s>\n",
dn->bv_val, age->age_dn.bv_val, 0);
modlist.sml_flags = SLAP_MOD_INTERNAL;
modlist.sml_next = NULL;
+ o.o_opid = 0;
o.o_tag = LDAP_REQ_MODIFY;
o.o_callback = &cb;
o.orm_modlist = &modlist;
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
o.o_req_dn = age->age_dn;
o.o_req_ndn = age->age_ndn;
o.o_permissive_modify = 1;
+ o.o_dont_replicate = 1;
+ o.orm_no_opattrs = 1;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
o.o_relax = SLAP_CONTROL_CRITICAL;
+ oex.oe_key = (void *)&autogroup;
+ LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
+
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &sreply );
o.o_bd->bd_info = (BackendInfo *)on;
+ op->o_opid = opid;
+ LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
return sreply.sr_err;
}
BerValue *vals, *nvals;
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
Operation o = *op;
+ unsigned long opid = op->o_opid;
+ OpExtra oex;
if ( dn == NULL || ndn == NULL ) {
Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_from_group removing all members from <%s>\n",
modlist->sml_flags = SLAP_MOD_INTERNAL;
modlist->sml_next = NULL;
+ o.o_opid = 0;
o.o_callback = &cb;
o.o_tag = LDAP_REQ_MODIFY;
o.orm_modlist = modlist;
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
o.o_req_dn = age->age_dn;
o.o_req_ndn = age->age_ndn;
o.o_relax = SLAP_CONTROL_CRITICAL;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
o.o_permissive_modify = 1;
+ o.o_dont_replicate = 1;
+ o.orm_no_opattrs = 1;
+
+ oex.oe_key = (void *)&autogroup;
+ LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &sreply );
o.o_bd->bd_info = (BackendInfo *)on;
+ LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
+
slap_mods_free( modlist, 1 );
+ op->o_opid = opid;
return sreply.sr_err;
}
SlapReply sreply = {REP_RESULT};
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
Operation o = *op;
+ unsigned long opid = op->o_opid;
+ OpExtra oex;
Debug(LDAP_DEBUG_TRACE, "==> autogroup_delete_member_values_from_group removing <%s> from <%s>\n",
dn->bv_val, age->age_dn.bv_val, 0);
modlist.sml_flags = SLAP_MOD_INTERNAL;
modlist.sml_next = NULL;
+ o.o_opid = 0;
o.o_tag = LDAP_REQ_MODIFY;
o.o_callback = &cb;
o.orm_modlist = &modlist;
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
o.o_req_dn = age->age_dn;
o.o_req_ndn = age->age_ndn;
o.o_permissive_modify = 1;
+ o.o_dont_replicate = 1;
+ o.orm_no_opattrs = 1;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
o.o_relax = SLAP_CONTROL_CRITICAL;
+ oex.oe_key = (void *)&autogroup;
+ LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
+
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &sreply );
o.o_bd->bd_info = (BackendInfo *)on;
+ op->o_opid = opid;
+
+ LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
return sreply.sr_err;
}
slap_callback cb = { 0 };
slap_callback null_cb = { NULL, slap_null_cb, NULL, NULL };
autogroup_ga_t agg;
+ OpExtra oex;
Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n",
age->age_dn.bv_val, 0, 0);
o.ors_attrsonly = 0;
o.o_tag = LDAP_REQ_SEARCH;
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
o.o_req_dn = agf->agf_dn;
o.o_req_ndn = agf->agf_ndn;
o.ors_tlimit = SLAP_NO_LIMIT;
o.ors_slimit = SLAP_NO_LIMIT;
o.ors_attrs = agf->agf_anlist ? agf->agf_anlist : slap_anlist_no_attrs;
+ o.o_do_not_cache = 1;
agg.agg_group = age;
agg.agg_filter = agf;
o.o_bd->bd_info = (BackendInfo *)on;
if ( modify == 1 && agg.agg_mod ) {
+ unsigned long opid = op->o_opid;
+
rs_reinit( &rs, REP_RESULT );
o = *op;
+ o.o_opid = 0;
o.o_callback = &null_cb;
o.o_tag = LDAP_REQ_MODIFY;
o.orm_modlist = agg.agg_mod;
+ o.o_dn = op->o_bd->be_rootdn;
+ o.o_ndn = op->o_bd->be_rootndn;
o.o_req_dn = age->age_dn;
o.o_req_ndn = age->age_ndn;
o.o_relax = SLAP_CONTROL_CRITICAL;
o.o_managedsait = SLAP_CONTROL_NONCRITICAL;
o.o_permissive_modify = 1;
+ o.o_dont_replicate = 1;
+ o.orm_no_opattrs = 1;
+
+ oex.oe_key = (void *)&autogroup;
+ LDAP_SLIST_INSERT_HEAD( &o.o_extra, &oex, oe_next );
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &rs );
o.o_bd->bd_info = (BackendInfo *)on;
+ LDAP_SLIST_REMOVE( &o.o_extra, &oex, OpExtra, oe_next );
+
slap_mods_free(agg.agg_mod, 1);
+ op->o_opid = opid;
}
return 0;
/*
** Adds a group to the internal list from the passed entry.
-** scan specifies whether to add all maching members to the group.
+** scan specifies whether to add all matching members to the group.
** modify specifies whether to modify the given group entry (when modify == 0),
** or to modify the group entry in the database (when modify == 1 and e = NULL and ndn != NULL).
** agi - pointer to the groups and the attribute definitions
} else {
autogroup_entry_t *age;
autogroup_filter_t *agf;
+ struct berval odn, ondn;
int rc;
+
+ /* must use rootdn when calling test_filter */
+ odn = op->o_dn;
+ ondn = op->o_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
for ( age = agi->agi_entry; age ; age = age->age_next ) {
ldap_pvt_thread_mutex_lock( &age->age_mutex );
}
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
}
+ op->o_dn = odn;
+ op->o_ndn = ondn;
}
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
autogroup_def_t *agd = agi->agi_def;
slap_callback *sc = NULL;
ag_addinfo *aa = NULL;
- int rc = 0;
Debug( LDAP_DEBUG_TRACE, "==> autogroup_add_entry <%s>\n",
op->ora_e->e_name.bv_val, 0, 0);
autogroup_filter_t *agf;
Entry *e;
int matched_group = 0, rc = 0;
+ struct berval odn, ondn;
+ OpExtra *oex;
+
+ LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
+ if ( oex->oe_key == (void *)&autogroup )
+ return SLAP_CB_CONTINUE;
+ }
Debug( LDAP_DEBUG_TRACE, "==> autogroup_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
/* Check if the entry matches any of the groups.
If yes, we can delete the entry from that group. */
+ odn = op->o_dn;
+ ondn = op->o_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
ldap_pvt_thread_mutex_lock( &age->age_mutex );
}
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
}
+ op->o_dn = odn;
+ op->o_ndn = ondn;
overlay_entry_release_ov( op, e, 0, on );
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
Entry *e, *group;
Attribute *a, *ea, *attrs;
int is_olddn, is_newdn, is_value_refresh, dn_equal;
+ OpExtra *oex;
+
+ LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
+ if ( oex->oe_key == (void *)&autogroup )
+ break;
+ }
/* 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 ) ) {
+ if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !oex ) {
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
}
} else if ( op->o_tag == LDAP_REQ_MODRDN ) {
- if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
+ if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !oex ) {
Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
}
/* For each group:
- 1. check if the orginal entry's DN is in the group.
- 2. chceck if the any of the group filter's base DN is a suffix of the new DN
+ 1. check if the original entry's DN is in the group.
+ 2. check if the any of the group filter's base DN is a suffix of the new DN
If 1 and 2 are both false, we do nothing.
If 1 and 2 is true, we remove the old DN from the group, and add the new DN.
}
if ( age->age_modrdn_olddnmodified ) {
- /* Resquest already marked this group to be updated */
+ /* Request already marked this group to be updated */
is_olddn = 1;
is_value_refresh = 1;
age->age_modrdn_olddnmodified = 0;
autogroup_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, age );
} else
if ( is_olddn == 0 && is_newdn == 1 ) {
+ Entry etmp;
+ struct berval odn, ondn;
+ etmp.e_name = op->o_req_dn;
+ etmp.e_nname = op->o_req_ndn;
+ etmp.e_attrs = attrs;
+ odn = op->o_dn;
+ ondn = op->o_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
for ( agf = age->age_filter; agf; agf = agf->agf_next ) {
- if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
+ if ( test_filter( op, &etmp, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
if ( ea ) {
autogroup_add_member_values_to_group( op, &new_dn, age, ea );
} else
break;
}
}
+ op->o_dn = odn;
+ op->o_ndn = ondn;
} else
if ( is_olddn == 1 && is_newdn == 1 && dn_equal != 0 ) {
if ( ea ) {
}
if ( op->o_tag == LDAP_REQ_MODIFY ) {
- if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op ) ) {
+ if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !oex ) {
+ Entry etmp;
+ struct berval odn, ondn;
Debug( LDAP_DEBUG_TRACE, "==> autogroup_response MODIFY <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_lock( &agi->agi_mutex );
*/
attrs = attrs_dup( e->e_attrs );
overlay_entry_release_ov( op, e, 0, on );
+ etmp.e_name = op->o_req_dn;
+ etmp.e_nname = op->o_req_ndn;
+ etmp.e_attrs = attrs;
+ odn = op->o_dn;
+ ondn = op->o_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
for ( age = agi->agi_entry ; age ; age = age->age_next ) {
is_olddn = 0;
is_newdn = 0;
-
ldap_pvt_thread_mutex_lock( &age->age_mutex );
if ( age->age_filter && age->age_filter->agf_anlist ) {
attrs_free( attrs );
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
+ op->o_dn = odn;
+ op->o_ndn = ondn;
return SLAP_CB_CONTINUE;
}
for ( agf = age->age_filter ; agf ; agf = agf->agf_next ) {
if ( dnIsSuffix( &op->o_req_ndn, &agf->agf_ndn ) ) {
- if ( test_filter( op, e, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
+ if ( test_filter( op, &etmp, agf->agf_filter ) == LDAP_COMPARE_TRUE ) {
is_newdn = 1;
break;
}
ldap_pvt_thread_mutex_unlock( &age->age_mutex );
}
+ op->o_dn = odn;
+ op->o_ndn = ondn;
attrs_free( attrs );
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
}
/*
-** When modifing a group, we must deny any modifications to the member attribute,
+** When modifying a group, we must deny any modifications to the member attribute,
** because the group would be inconsistent.
*/
static int
autogroup_entry_t *age;
Entry *e;
Attribute *a;
+ struct berval odn, ondn;
+ OpExtra *oex;
- if ( get_manageDSAit( op ) ) {
- return SLAP_CB_CONTINUE;
+ LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
+ if ( oex->oe_key == (void *)&autogroup )
+ return SLAP_CB_CONTINUE;
}
Debug( LDAP_DEBUG_TRACE, "==> autogroup_modify_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
return SLAP_CB_CONTINUE;
}
+ odn = op->o_dn;
+ ondn = op->o_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
/* Must refresh groups if a matching member value is modified OR filter contains memberOf=DN */
for ( age = agi->agi_entry; age ; age = age->age_next ) {
autogroup_filter_t *agf;
}
}
}
+ op->o_dn = odn;
+ op->o_ndn = ondn;
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
}
}
- overlay_entry_release_ov( op, e, 0, on );
- ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
- return SLAP_CB_CONTINUE;
+ /* an entry may only have one dynamic group class */
+ break;
}
}
autogroup_info_t *agi = (autogroup_info_t *)on->on_bi.bi_private;
autogroup_entry_t *age;
Entry *e;
+ struct berval odn, ondn;
+ OpExtra *oex;
- if ( get_manageDSAit( op ) ) {
- return SLAP_CB_CONTINUE;
+ LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
+ if ( oex->oe_key == (void *)&autogroup )
+ return SLAP_CB_CONTINUE;
}
Debug( LDAP_DEBUG_TRACE, "==> autogroup_modrdn_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
return SLAP_CB_CONTINUE;
}
+ odn = op->o_dn;
+ ondn = op->o_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
/* Must check if a dn is modified */
for ( age = agi->agi_entry; age ; age = age->age_next ) {
autogroup_filter_t *agf;
}
}
}
+ op->o_dn = odn;
+ op->o_ndn = ondn;
overlay_entry_release_ov( op, e, 0, on );
ldap_pvt_thread_mutex_unlock( &agi->agi_mutex );
op->ors_tlimit = SLAP_NO_LIMIT;
op->ors_slimit = SLAP_NO_LIMIT;
op->ors_attrs = slap_anlist_no_attrs;
+ op->o_do_not_cache = 1;
op->o_bd = be;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
return 0;
}
-static slap_overinst autogroup = { { NULL } };
-
static
int
autogroup_initialize(void)