ITS#9121 support nested groups

This commit is contained in:
Howard Chu 2020-07-01 14:37:55 +01:00 committed by Quanah Gibson-Mount
parent 9210ed1618
commit 2c0499ae4e
4 changed files with 1076 additions and 161 deletions

View file

@ -51,7 +51,7 @@ occurrences, and it must appear after the
.B overlay
directive.
.TP
.B dynlist\-attrset <group-oc> [<URI>] <URL-ad> [[<mapped-ad>:]<member-ad>[+<memberOf-ad] ...]
.B dynlist\-attrset <group-oc> [<URI>] <URL-ad> [[<mapped-ad>:]<member-ad>[+<memberOf-ad[@<static-oc>[*]] ...]
The value
.B group\-oc
is the name of the objectClass that triggers the dynamic expansion of the
@ -94,6 +94,15 @@ If the optional
.B memberOf-ad
attribute is also specified, then it will be populated with the DNs of the
dynamic groups that an entry is a member of.
If the optional
.B static-oc
objectClass is also specified, then the memberOf attribute will also be
populated with the DNs of the static groups that an entry is a member of.
If the optional
.B *
character is also specified, then the member and memberOf values will be
populated recursively, for nested groups. Note that currently nesting is
only supported for Search operations, not Compares.
Alternatively,
.B mapped-ad

View file

@ -44,6 +44,8 @@ typedef struct dynlist_map_t {
AttributeDescription *dlm_memberOf_ad;
ObjectClass *dlm_static_oc;
int dlm_memberOf_nested;
int dlm_member_oper;
int dlm_memberOf_oper;
struct dynlist_map_t *dlm_next;
} dynlist_map_t;
@ -63,7 +65,6 @@ typedef struct dynlist_gen_t {
dynlist_info_t *dlg_dli;
int dlg_memberOf;
} dynlist_gen_t;
#define DYNLIST_HAS_MEMBEROF 1
#define DYNLIST_USAGE \
"\"dynlist-attrset <oc> [uri] <URL-ad> [[<mapped-ad>:]<member-ad>[+<memberOf-ad>[@<static-oc>[*]] ...]\": "
@ -100,8 +101,6 @@ ad_infilter( AttributeDescription *ad, Filter *f )
static int
dynlist_make_filter( Operation *op, Entry *e, dynlist_info_t *dli, const char *url, struct berval *oldf, struct berval *newf )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
char *ptr;
int needBrackets = 0;
@ -326,9 +325,160 @@ done:;
return 0;
}
typedef struct dynlist_name_t {
struct berval dy_name;
dynlist_info_t *dy_dli;
AttributeDescription *dy_staticmember;
int dy_seen;
int dy_numuris;
TAvlnode *dy_subs;
TAvlnode *dy_sups;
LDAPURLDesc *dy_uris[];
} dynlist_name_t;
static void
dynlist_urlmembers( Operation *op, dynlist_name_t *dyn, slap_callback *sc )
{
Operation o = *op;
LDAPURLDesc *ludp;
int i;
o.ors_deref = LDAP_DEREF_NEVER;
o.ors_limit = NULL;
o.ors_tlimit = SLAP_NO_LIMIT;
o.ors_slimit = SLAP_NO_LIMIT;
o.ors_attrs = NULL;
o.o_callback = sc;
for (i=0; i<dyn->dy_numuris; i++) {
ludp = dyn->dy_uris[i];
if ( ludp->lud_attrs )
continue;
o.o_req_dn.bv_val = ludp->lud_dn;
o.o_req_dn.bv_len = ludp->lud_port;
o.o_req_ndn = o.o_req_dn;
o.ors_scope = ludp->lud_scope;
o.ors_filter = (Filter *)ludp->lud_filter;
filter2bv_x( op, o.ors_filter, &o.ors_filterstr );
o.o_bd = select_backend( &o.o_req_ndn, 1 );
if ( o.o_bd && o.o_bd->be_search ) {
SlapReply r = { REP_SEARCH };
r.sr_attr_flags = slap_attr_flags( o.ors_attrs );
o.o_managedsait = SLAP_CONTROL_CRITICAL;
(void)o.o_bd->be_search( &o, &r );
}
op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
}
}
static void
dynlist_nested_memberOf( Entry *e, AttributeDescription *ad, TAvlnode *sups )
{
TAvlnode *ptr;
dynlist_name_t *dyn;
Attribute *a;
a = attr_find( e->e_attrs, ad );
for ( ptr = tavl_end( sups, TAVL_DIR_LEFT ); ptr;
ptr = tavl_next( ptr, TAVL_DIR_RIGHT )) {
dyn = ptr->avl_data;
if ( a ) {
unsigned slot;
if ( attr_valfind( a, SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
&dyn->dy_name, &slot, NULL ) == LDAP_SUCCESS )
continue;
}
attr_merge_one( e, ad, &dyn->dy_name, &dyn->dy_name );
if ( !a )
a = attr_find( e->e_attrs, ad );
if ( dyn->dy_sups )
dynlist_nested_memberOf( e, ad, dyn->dy_sups );
}
}
typedef struct dynlist_member_t {
Entry *dm_e;
AttributeDescription *dm_ad;
Modification dm_mod;
TAvlnode *dm_groups;
struct berval dm_bv[2];
struct berval dm_nbv[2];
const char *dm_text;
char dm_textbuf[1024];
} dynlist_member_t;
static int
dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
dynlist_ptr_cmp( const void *c1, const void *c2 )
{
return ( c1 < c2 ) ? -1 : c1 > c2;
}
static int
dynlist_nested_member_dg( Operation *op, SlapReply *rs )
{
dynlist_member_t *dm = op->o_callback->sc_private;
if ( rs->sr_type != REP_SEARCH )
return LDAP_SUCCESS;
dm->dm_bv[0] = rs->sr_entry->e_name;
dm->dm_nbv[0] = rs->sr_entry->e_nname;
modify_add_values( dm->dm_e, &dm->dm_mod, /* permissive */ 1,
&dm->dm_text, dm->dm_textbuf, sizeof( dm->dm_textbuf ));
return LDAP_SUCCESS;
}
static void
dynlist_nested_member( Operation *op, dynlist_member_t *dm, TAvlnode *subs )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
TAvlnode *ptr;
dynlist_name_t *dyn;
Entry *ne;
Attribute *a, *b;
a = attr_find( dm->dm_e->e_attrs, dm->dm_ad );
if ( !a )
return;
for ( ptr = tavl_end( subs, TAVL_DIR_LEFT ); ptr;
ptr = tavl_next( ptr, TAVL_DIR_RIGHT )) {
dyn = ptr->avl_data;
if ( tavl_insert( &dm->dm_groups, dyn, dynlist_ptr_cmp, avl_dup_error ))
continue;
if ( overlay_entry_get_ov( op, &dyn->dy_name, NULL, NULL, 0, &ne, on ) != LDAP_SUCCESS || ne == NULL )
continue;
b = attr_find( ne->e_attrs, dm->dm_ad );
if ( b ) {
dm->dm_mod.sm_values = b->a_vals;
dm->dm_mod.sm_nvalues = b->a_nvals;
dm->dm_mod.sm_numvals = b->a_numvals;
modify_add_values( dm->dm_e, &dm->dm_mod, /* permissive */ 1,
&dm->dm_text, dm->dm_textbuf, sizeof( dm->dm_textbuf ));
}
overlay_entry_release_ov( op, ne, 0, on );
if ( dyn->dy_numuris ) {
slap_callback cb = { 0 };
cb.sc_private = dm;
BER_BVZERO( &dm->dm_bv[1] );
BER_BVZERO( &dm->dm_nbv[1] );
dm->dm_mod.sm_values = dm->dm_bv;
dm->dm_mod.sm_nvalues = dm->dm_nbv;
dm->dm_mod.sm_numvals = 1;
cb.sc_response = dynlist_nested_member_dg;
dynlist_urlmembers( op, dyn, &cb );
}
if ( dyn->dy_subs )
dynlist_nested_member( op, dm, dyn->dy_subs );
}
}
static int
dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli, dynlist_name_t *dyn )
{
Attribute *a, *id = NULL;
slap_callback cb = { 0 };
@ -340,10 +490,11 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
dynlist_sc_t dlc = { 0 };
dynlist_map_t *dlm;
e = rs->sr_entry;
a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad );
if ( a == NULL ) {
/* FIXME: error? */
return SLAP_CB_CONTINUE;
goto checkdyn;
}
opattrs = SLAP_OPATTRS( rs->sr_attr_flags );
@ -357,7 +508,7 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
break;
}
if ( dli->dli_dlm && !dlm )
return SLAP_CB_CONTINUE;
goto checkdyn;
if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) {
Attribute *authz = NULL;
@ -370,7 +521,7 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
if ( slap_sasl_matches( op, authz->a_nvals,
&o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS )
{
return SLAP_CB_CONTINUE;
goto checkdyn;
}
}
@ -379,7 +530,6 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
o.o_groups = NULL;
}
e = rs->sr_entry;
/* ensure e is modifiable, but do not replace
* sr_entry yet since we have pointers into it */
if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
@ -536,11 +686,16 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
&dli->dli_default_filter, op->o_tmpmemctx );
} else {
struct berval flt;
ber_str2bv( lud->lud_filter, 0, 0, &flt );
if ( dynlist_make_filter( op, rs->sr_entry, dli, url->bv_val, &flt, &o.ors_filterstr ) ) {
/* error */
goto cleanup;
/* don't allow recursion in lists */
if ( lud->lud_attrs ) {
struct berval flt;
ber_str2bv( lud->lud_filter, 0, 0, &flt );
if ( dynlist_make_filter( op, rs->sr_entry, dli, url->bv_val, &flt, &o.ors_filterstr ) ) {
/* error */
goto cleanup;
}
} else {
ber_str2bv( lud->lud_filter, 0, 0, &o.ors_filterstr );
}
}
o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val );
@ -574,12 +729,51 @@ cleanup:;
if ( !BER_BVISNULL( &o.o_req_ndn ) ) {
op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx );
}
assert( BER_BVISNULL( &o.ors_filterstr )
|| o.ors_filterstr.bv_val != lud->lud_filter );
op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
if ( lud->lud_attrs ) {
assert( BER_BVISNULL( &o.ors_filterstr )
|| o.ors_filterstr.bv_val != lud->lud_filter );
op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
} else {
if ( o.ors_filterstr.bv_val != lud->lud_filter )
op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx );
}
ldap_free_urldesc( lud );
}
checkdyn:
/* handle nested groups */
if ( dyn && ( dyn->dy_sups || dyn->dy_subs )) {
/* ensure e is modifiable */
if ( e == rs->sr_entry && !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
e = entry_dup( rs->sr_entry );
rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
}
if ( dyn->dy_subs ) {
for ( dlm = dyn->dy_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_member_ad ) {
dynlist_member_t dm;
dm.dm_groups = NULL;
dm.dm_mod.sm_op = LDAP_MOD_ADD;
dm.dm_mod.sm_desc = dlm->dlm_member_ad;
dm.dm_mod.sm_type = dlm->dlm_member_ad->ad_cname;
dm.dm_e = e;
dm.dm_ad = dlm->dlm_member_ad;
dynlist_nested_member( op, &dm, dyn->dy_subs );
if ( dm.dm_groups )
tavl_free( dm.dm_groups, NULL );
}
}
}
if ( dyn->dy_sups ) {
for ( dlm = dyn->dy_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_memberOf_ad ) {
dynlist_nested_memberOf( e, dlm->dlm_memberOf_ad, dyn->dy_sups );
}
}
}
}
if ( e != rs->sr_entry ) {
rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
@ -769,7 +963,7 @@ done:;
r.sr_attrs = an;
o.o_acl_priv = ACL_COMPARE;
dynlist_prepare_entry( &o, &r, dli );
dynlist_prepare_entry( &o, &r, dli, NULL );
a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc );
ret = LDAP_NO_SUCH_ATTRIBUTE;
@ -798,22 +992,18 @@ release:;
return ret;
}
typedef struct dynlist_name_t {
struct berval dy_name;
dynlist_info_t *dy_dli;
AttributeDescription *dy_staticmember;
int dy_seen;
int dy_numuris;
LDAPURLDesc *dy_uris[];
} dynlist_name_t;
#define WANT_MEMBEROF 1
#define WANT_MEMBER 2
typedef struct dynlist_search_t {
TAvlnode *ds_names;
TAvlnode *ds_fnodes;
dynlist_info_t *ds_dli;
dynlist_map_t *ds_dlm;
Filter *ds_origfilter;
struct berval ds_origfilterbv;
int ds_memberOf;
int ds_want;
int ds_found;
} dynlist_search_t;
static int
@ -900,6 +1090,8 @@ dynlist_search1resp( Operation *op, SlapReply *rs )
ldap_free_urldesc( ludp );
}
ch_free( dyn );
} else {
ds->ds_found++;
}
}
}
@ -911,7 +1103,7 @@ dynlist_search1resp( Operation *op, SlapReply *rs )
* using (&(entryDN=<groupURIbase>)<groupURIfilter>)
*/
static int
dynlist_filter_dyngroup( Operation *op, Filter *f, Filter *n, Attribute *a )
dynlist_filter_dyngroup( Operation *op, Filter *n, Attribute *a )
{
Filter *andf = NULL, *dnf, *urif, *orf = NULL;
LDAPURLDesc *ludp;
@ -940,23 +1132,24 @@ dynlist_filter_dyngroup( Operation *op, Filter *f, Filter *n, Attribute *a )
} else {
urif = NULL;
}
if ( !andf ) {
if ( !andf && n->f_choice == SLAPD_FILTER_COMPUTED ) {
andf = n;
andf->f_next = NULL;
} else {
if ( !orf ) {
orf = n;
if ( n->f_choice != LDAP_FILTER_OR ) {
andf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
andf->f_choice = n->f_choice;
andf->f_list = n->f_list;
orf = n;
*andf = *n;
orf->f_choice = LDAP_FILTER_OR;
orf->f_next = NULL;
orf->f_list = andf;
}
andf->f_next = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
andf = andf->f_next;
andf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
andf->f_next = orf->f_list;
orf->f_list = andf;
}
dnf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
andf->f_choice = LDAP_FILTER_AND;
andf->f_next = NULL;
andf->f_list = dnf;
dnf->f_next = urif;
if ( ludp->lud_scope == LDAP_SCOPE_BASE ) {
@ -994,32 +1187,39 @@ dynlist_filter_dyngroup( Operation *op, Filter *f, Filter *n, Attribute *a )
* using (|(entryDN=<memberN>)[...])
*/
static int
dynlist_filter_stgroup( Operation *op, Filter *f, Filter *n, Attribute *a )
dynlist_filter_stgroup( Operation *op, Filter *n, Attribute *a )
{
Filter *dnf, *orf;
Filter *dnf, *orf = NULL;
int i;
if ( a->a_numvals == 1 ) {
if ( a->a_numvals == 1 && n->f_choice == SLAPD_FILTER_COMPUTED ) {
dnf = n;
dnf->f_next = NULL;
} else {
orf = n;
orf->f_choice = LDAP_FILTER_OR;
orf->f_next = NULL;
if ( n->f_choice != LDAP_FILTER_OR ) {
dnf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
*dnf = *n;
orf->f_choice = LDAP_FILTER_OR;
orf->f_next = NULL;
orf->f_list = dnf;
}
dnf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
dnf->f_next = orf->f_list;
orf->f_list = dnf;
}
for (i=0; i<a->a_numvals; i++) {
if ( i > 1 ) {
dnf->f_next = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
dnf = dnf->f_next;
if ( i ) {
dnf = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
dnf->f_next = orf->f_list;
orf->f_list = dnf;
}
dnf->f_choice = LDAP_FILTER_EQUALITY;
dnf->f_ava = op->o_tmpcalloc( 1, sizeof(AttributeAssertion), op->o_tmpmemctx );
dnf->f_av_desc = slap_schema.si_ad_entryDN;
ber_dupbv_x( &dnf->f_av_value, &a->a_nvals[i], op->o_tmpmemctx );
}
dnf->f_next = NULL;
return 0;
}
@ -1027,29 +1227,42 @@ dynlist_filter_stgroup( Operation *op, Filter *f, Filter *n, Attribute *a )
* its members.
*/
static int
dynlist_filter_group( Operation *op, Filter *f, Filter *n, dynlist_search_t *ds )
dynlist_filter_group( Operation *op, dynlist_name_t *dyn, Filter *n, dynlist_search_t *ds )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
Entry *e;
Attribute *a;
int rc = -1;
if ( overlay_entry_get_ov( op, &f->f_av_value, NULL, NULL, 0, &e, on ) !=
if ( tavl_insert( &ds->ds_fnodes, dyn, dynlist_ptr_cmp, avl_dup_error ))
return 0;
if ( overlay_entry_get_ov( op, &dyn->dy_name, NULL, NULL, 0, &e, on ) !=
LDAP_SUCCESS || e == NULL ) {
return -1;
}
if ( ds->ds_dlm->dlm_static_oc && is_entry_objectclass( e, ds->ds_dlm->dlm_static_oc, 0 )) {
a = attr_find( e->e_attrs, ds->ds_dlm->dlm_member_ad );
if ( a ) {
rc = dynlist_filter_stgroup( op, f, n, a );
rc = dynlist_filter_stgroup( op, n, a );
}
} else {
a = attr_find( e->e_attrs, ds->ds_dli->dli_ad );
if ( a ) {
rc = dynlist_filter_dyngroup( op, f, n, a );
rc = dynlist_filter_dyngroup( op, n, a );
}
}
overlay_entry_release_ov( op, e, 0, on );
if ( dyn->dy_subs && !rc ) {
TAvlnode *ptr;
for ( ptr = tavl_end( dyn->dy_subs, TAVL_DIR_LEFT ); ptr;
ptr = tavl_next( ptr, TAVL_DIR_RIGHT )) {
dyn = ptr->avl_data;
rc = dynlist_filter_group( op, dyn, n, ds );
if ( rc )
break;
}
}
return rc;
}
@ -1076,8 +1289,12 @@ dynlist_filter_dup( Operation *op, Filter *f, AttributeDescription *ad, dynlist_
break;
case LDAP_FILTER_EQUALITY:
if ( f->f_av_desc == ad && !dynlist_filter_group( op, f, n, ds ))
break;
n->f_choice = SLAPD_FILTER_COMPUTED;
if ( f->f_av_desc == ad ) {
dynlist_name_t *dyn = tavl_find( ds->ds_names, &f->f_av_value, dynlist_avl_cmp );
if ( dyn && !dynlist_filter_group( op, dyn, n, ds ))
break;
}
/* FALLTHRU */
case LDAP_FILTER_GE:
case LDAP_FILTER_LE:
@ -1155,6 +1372,10 @@ dynlist_search_free( void *ptr )
}
ldap_free_urldesc( ludp );
}
if ( dyn->dy_subs )
tavl_free( dyn->dy_subs, NULL );
if ( dyn->dy_sups )
tavl_free( dyn->dy_sups, NULL );
ch_free( ptr );
}
@ -1166,6 +1387,8 @@ dynlist_search_cleanup( Operation *op, SlapReply *rs )
slap_callback *sc = op->o_callback;
dynlist_search_t *ds = op->o_callback->sc_private;
tavl_free( ds->ds_names, dynlist_search_free );
if ( ds->ds_fnodes )
tavl_free( ds->ds_fnodes, NULL );
if ( ds->ds_origfilter ) {
op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
dynlist_filter_free( op, op->ors_filter );
@ -1180,7 +1403,7 @@ dynlist_search_cleanup( Operation *op, SlapReply *rs )
}
static int
dynlist_testurl(Operation *op, dynlist_name_t *dyn, Entry *e)
dynlist_test_membership(Operation *op, dynlist_name_t *dyn, Entry *e)
{
LDAPURLDesc *ludp;
struct berval nbase, bv;
@ -1233,6 +1456,52 @@ dynlist_testurl(Operation *op, dynlist_name_t *dyn, Entry *e)
return rc;
}
static void
dynlist_add_memberOf(Operation *op, SlapReply *rs, dynlist_search_t *ds)
{
TAvlnode *ptr;
Entry *e = rs->sr_entry;
dynlist_name_t *dyn;
Attribute *a;
/* See if there are any memberOf values to attach to this entry */
for ( ptr = tavl_end( ds->ds_names, TAVL_DIR_LEFT ); ptr;
ptr = tavl_next( ptr, TAVL_DIR_RIGHT )) {
dynlist_map_t *dlm;
dyn = ptr->avl_data;
for ( dlm = dyn->dy_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_memberOf_ad ) {
if ( dynlist_test_membership( op, dyn, e ) == LDAP_COMPARE_TRUE ) {
/* ensure e is modifiable, but do not replace
* sr_entry yet since we have pointers into it */
if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) && e == rs->sr_entry ) {
e = entry_dup( rs->sr_entry );
}
a = attr_find( e->e_attrs, dlm->dlm_memberOf_ad );
if ( a ) {
unsigned slot;
if ( attr_valfind( a, SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
&dyn->dy_name, &slot, NULL ) != LDAP_SUCCESS )
a = NULL;
}
if ( !a )
attr_merge_one( e, dlm->dlm_memberOf_ad, &dyn->dy_name, &dyn->dy_name );
if ( dyn->dy_sups ) {
dynlist_nested_memberOf( e, dlm->dlm_memberOf_ad, dyn->dy_sups );
}
break;
}
}
}
}
if ( e != rs->sr_entry ) {
rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
}
}
/* process the search responses */
static int
dynlist_search2resp( Operation *op, SlapReply *rs )
@ -1242,52 +1511,24 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
int rc;
if ( rs->sr_type == REP_SEARCH && rs->sr_entry != NULL ) {
rc = SLAP_CB_CONTINUE;
/* See if this is one of our dynamic entries */
dyn = tavl_find( ds->ds_names, &rs->sr_entry->e_nname, dynlist_avl_cmp );
if ( dyn ) {
Entry *e = rs->sr_entry;
dyn->dy_seen = 1;
rc = dynlist_prepare_entry( op, rs, dyn->dy_dli );
if ( ds->ds_origfilter && test_filter( op, rs->sr_entry, ds->ds_origfilter ) != LDAP_COMPARE_TRUE ) {
if ( e != rs->sr_entry )
rs_flush_entry( op, rs, NULL );
rc = LDAP_SUCCESS;
}
return rc;
} else if ( ds->ds_memberOf ) {
TAvlnode *ptr;
Entry *e = rs->sr_entry;
/* See if there are any memberOf values to attach to this entry */
for ( ptr = tavl_end( ds->ds_names, TAVL_DIR_LEFT ); ptr;
ptr = tavl_next( ptr, TAVL_DIR_RIGHT )) {
dynlist_map_t *dlm;
dyn = ptr->avl_data;
for ( dlm = dyn->dy_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_memberOf_ad ) {
if ( dynlist_testurl( op, dyn, e ) == LDAP_COMPARE_TRUE ) {
/* ensure e is modifiable, but do not replace
* sr_entry yet since we have pointers into it */
if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) && e == rs->sr_entry ) {
e = entry_dup( rs->sr_entry );
}
attr_merge_one( e, dlm->dlm_memberOf_ad, &dyn->dy_name, &dyn->dy_name );
break;
}
}
}
}
if ( e != rs->sr_entry ) {
rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e );
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
}
if ( ds->ds_origfilter && test_filter( op, rs->sr_entry, ds->ds_origfilter ) != LDAP_COMPARE_TRUE ) {
rs_flush_entry( op, rs, NULL );
return LDAP_SUCCESS;
}
rc = dynlist_prepare_entry( op, rs, dyn->dy_dli, dyn );
} else if ( ds->ds_want )
dynlist_add_memberOf( op, rs, ds );
if ( ds->ds_origfilter && test_filter( op, rs->sr_entry, ds->ds_origfilter ) != LDAP_COMPARE_TRUE ) {
rs_flush_entry( op, rs, NULL );
return LDAP_SUCCESS;
}
return rc;
} else if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS ) {
TAvlnode *ptr;
SlapReply r = *rs;
Filter *f = ds->ds_origfilter ? ds->ds_origfilter : op->ors_filter;
/* Check for any unexpanded dynamic group entries that weren't picked up
* by the original search filter.
*/
@ -1302,8 +1543,8 @@ dynlist_search2resp( Operation *op, SlapReply *rs )
r.sr_entry == NULL )
continue;
r.sr_flags = REP_ENTRY_MUSTRELEASE;
dynlist_prepare_entry( op, &r, dyn->dy_dli );
if ( test_filter( op, r.sr_entry, op->ors_filter ) == LDAP_COMPARE_TRUE ) {
dynlist_prepare_entry( op, &r, dyn->dy_dli, dyn );
if ( test_filter( op, r.sr_entry, f ) == LDAP_COMPARE_TRUE ) {
r.sr_attrs = op->ors_attrs;
rs->sr_err = send_search_entry( op, &r );
if ( rs->sr_err != LDAP_SUCCESS )
@ -1333,6 +1574,79 @@ dynlist_fix_filter( Operation *op, AttributeDescription *ad, dynlist_search_t *d
filter2bv_x( op, f, &op->ors_filterstr );
}
typedef struct dynlist_link_t {
dynlist_search_t *dl_ds;
dynlist_name_t *dl_sup;
} dynlist_link_t;
static int
dynlist_nestlink_dg( Operation *op, SlapReply *rs )
{
dynlist_link_t *dll = op->o_callback->sc_private;
dynlist_search_t *ds = dll->dl_ds;
dynlist_name_t *di = dll->dl_sup, *dj;
if ( rs->sr_type != REP_SEARCH )
return LDAP_SUCCESS;
dj = tavl_find( dll->dl_ds->ds_names, &rs->sr_entry->e_nname, dynlist_avl_cmp );
if ( dj ) {
if ( ds->ds_want & WANT_MEMBEROF ) {
tavl_insert( &dj->dy_sups, di, dynlist_ptr_cmp, avl_dup_error );
}
if ( ds->ds_want & WANT_MEMBER ) {
tavl_insert( &di->dy_subs, dj, dynlist_ptr_cmp, avl_dup_error );
}
}
return LDAP_SUCCESS;
}
/* Connect all nested groups to their parents/children */
static void
dynlist_nestlink( Operation *op, dynlist_search_t *ds )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
dynlist_name_t *di, *dj;
TAvlnode *ptr;
Entry *e;
Attribute *a;
int i;
for ( ptr = tavl_end( ds->ds_names, TAVL_DIR_LEFT ); ptr;
ptr = tavl_next( ptr, TAVL_DIR_RIGHT )) {
di = ptr->avl_data;
if ( ds->ds_dlm ) {
if ( overlay_entry_get_ov( op, &di->dy_name, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL )
continue;
a = attr_find( e->e_attrs, ds->ds_dlm->dlm_member_ad );
if ( a ) {
for ( i=0; i < a->a_numvals; i++ ) {
dj = tavl_find( ds->ds_names, &a->a_nvals[i], dynlist_avl_cmp );
if ( dj ) {
if ( ds->ds_want & WANT_MEMBEROF ) {
tavl_insert( &dj->dy_sups, di, dynlist_ptr_cmp, avl_dup_error );
}
if ( ds->ds_want & WANT_MEMBER ) {
tavl_insert( &di->dy_subs, dj, dynlist_ptr_cmp, avl_dup_error );
}
}
}
}
overlay_entry_release_ov( op, e, 0, on );
}
if ( di->dy_numuris ) {
slap_callback cb = { 0 };
dynlist_link_t dll;
dll.dl_ds = ds;
dll.dl_sup = di;
cb.sc_private = &dll;
cb.sc_response = dynlist_nestlink_dg;
dynlist_urlmembers( op, di, &cb );
}
}
}
static int
dynlist_search( Operation *op, SlapReply *rs )
{
@ -1347,7 +1661,9 @@ dynlist_search( Operation *op, SlapReply *rs )
slap_callback *sc;
dynlist_search_t *ds;
ObjectClass *static_oc = NULL;
ObjectClass *static_oc;
int nested, found, tmpwant;
int opattrs, userattrs;
if ( get_manageDSAit( op ) )
return SLAP_CB_CONTINUE;
@ -1355,82 +1671,105 @@ dynlist_search( Operation *op, SlapReply *rs )
sc = op->o_tmpcalloc( 1, sizeof(slap_callback)+sizeof(dynlist_search_t), op->o_tmpmemctx );
sc->sc_private = (void *)(sc+1);
ds = sc->sc_private;
ds->ds_memberOf = 0;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
/* Are we using memberOf, and does it affect this request? */
if ( dlg->dlg_memberOf ) {
int attrflags = slap_attr_flags( op->ors_attrs );
int opattrs = SLAP_OPATTRS( attrflags );
int userattrs = SLAP_USERATTRS( attrflags );
for ( dli = dlg->dlg_dli; dli; dli = dli->dli_next ) {
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_memberOf_ad ) {
/* if attribute is in filter, fix it */
if ( ad_infilter( dlm->dlm_memberOf_ad, op->ors_filter )) {
ds->ds_dli = dli;
ds->ds_dlm = dlm;
dynlist_fix_filter( op, dlm->dlm_memberOf_ad, ds );
}
/* if attribute is not requested, skip it */
if ( op->ors_attrs == NULL ) {
if ( is_at_operational( dlm->dlm_memberOf_ad->ad_type ) ) {
continue;
}
} else {
if ( is_at_operational( dlm->dlm_memberOf_ad->ad_type ) ) {
if ( !opattrs && !ad_inlist( dlm->dlm_memberOf_ad, op->ors_attrs ) )
{
continue;
}
} else {
if ( !userattrs && !ad_inlist( dlm->dlm_memberOf_ad, op->ors_attrs ) )
{
continue;
}
}
}
ds->ds_memberOf = 1;
if ( dlm->dlm_static_oc ) {
static_oc = dlm->dlm_static_oc;
ds->ds_dlm = dlm;
}
}
}
}
}
if ( static_oc ) {
f[0].f_choice = LDAP_FILTER_OR;
f[0].f_list = &f[1];
f[0].f_next = NULL;
f[1].f_choice = LDAP_FILTER_EQUALITY;
f[1].f_ava = &ava[0];
f[1].f_av_desc = slap_schema.si_ad_objectClass;
f[1].f_next = &f[2];
f[2].f_choice = LDAP_FILTER_EQUALITY;
f[2].f_ava = &ava[1];
f[2].f_av_desc = slap_schema.si_ad_objectClass;
f[2].f_next = NULL;
} else {
f[0].f_choice = LDAP_FILTER_EQUALITY;
f[0].f_ava = ava;
f[0].f_av_desc = slap_schema.si_ad_objectClass;
f[0].f_next = NULL;
opattrs = SLAP_OPATTRS( attrflags );
userattrs = SLAP_USERATTRS( attrflags );
}
/* Find all groups in scope. For group expansion
* we only need the groups within the search scope, but
* for memberOf populating, we need all dyngroups.
*/
for ( dli = dlg->dlg_dli; dli != NULL; dli = dli->dli_next ) {
for ( dli = dlg->dlg_dli; dli; dli = dli->dli_next ) {
static_oc = NULL;
nested = 0;
tmpwant = 0;
if ( dlg->dlg_memberOf ) {
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_memberOf_ad ) {
int want = 0;
/* with nesting, filter attributes also require nestlink */
if ( dlm->dlm_memberOf_nested ) {
/* WANT_ flags have inverted meaning here:
* to satisfy (memberOf=) filter, we need to also
* find all subordinate groups. No special
* treatment is needed for (member=) since we
* already search all group entries.
*/
if ( ad_infilter( dlm->dlm_memberOf_ad, op->ors_filter ))
want |= WANT_MEMBER;
}
/* if attribute is not requested, skip it */
if ( op->ors_attrs == NULL ) {
if ( !dlm->dlm_memberOf_oper )
want |= WANT_MEMBEROF;
if ( dlm->dlm_memberOf_nested && !dlm->dlm_member_oper )
want |= WANT_MEMBER;
} else {
if ( ad_inlist( dlm->dlm_memberOf_ad, op->ors_attrs ))
want |= WANT_MEMBEROF;
if ( dlm->dlm_memberOf_nested && ad_inlist( dlm->dlm_member_ad, op->ors_attrs )) {
want |= WANT_MEMBER;
} else {
if ( opattrs ) {
if ( dlm->dlm_memberOf_oper )
want |= WANT_MEMBEROF;
if ( dlm->dlm_memberOf_nested && dlm->dlm_member_oper )
want |= WANT_MEMBER;
}
if ( userattrs ) {
if ( !dlm->dlm_memberOf_oper )
want |= WANT_MEMBEROF;
if ( dlm->dlm_memberOf_nested && !dlm->dlm_member_oper )
want |= WANT_MEMBER;
}
}
}
if ( want ) {
nested = dlm->dlm_memberOf_nested;
ds->ds_want = tmpwant = want;
if ( dlm->dlm_static_oc ) {
static_oc = dlm->dlm_static_oc;
ds->ds_dlm = dlm;
}
}
}
}
}
if ( static_oc ) {
f[0].f_choice = LDAP_FILTER_OR;
f[0].f_list = &f[1];
f[0].f_next = NULL;
f[1].f_choice = LDAP_FILTER_EQUALITY;
f[1].f_next = &f[2];
f[1].f_ava = &ava[0];
f[1].f_av_desc = slap_schema.si_ad_objectClass;
f[1].f_av_value = dli->dli_oc->soc_cname;
f[2].f_choice = LDAP_FILTER_EQUALITY;
f[2].f_ava = &ava[1];
f[2].f_av_desc = slap_schema.si_ad_objectClass;
f[2].f_av_value = static_oc->soc_cname;
f[2].f_next = NULL;
} else {
f[0].f_choice = LDAP_FILTER_EQUALITY;
f[0].f_ava = ava;
f[0].f_av_desc = slap_schema.si_ad_objectClass;
f[0].f_av_value = dli->dli_oc->soc_cname;
f[0].f_next = NULL;
}
if ( o.o_callback != sc ) {
o.o_callback = sc;
o.ors_filter = f;
if ( ds->ds_memberOf ) {
if ( tmpwant ) {
o.o_req_dn = op->o_bd->be_suffix[0];
o.o_req_ndn = op->o_bd->be_nsuffix[0];
o.ors_scope = LDAP_SCOPE_SUBTREE;
@ -1445,22 +1784,20 @@ dynlist_search( Operation *op, SlapReply *rs )
BER_BVZERO( &o.ors_filterstr );
sc->sc_response = dynlist_search1resp;
}
ds->ds_dli = dli;
if ( static_oc ) {
f[1].f_av_value = dli->dli_oc->soc_cname;
f[2].f_av_value = static_oc->soc_cname;
} else {
f[0].f_av_value = dli->dli_oc->soc_cname;
}
if ( o.ors_filterstr.bv_val )
o.o_tmpfree( o.ors_filterstr.bv_val, o.o_tmpmemctx );
filter2bv_x( &o, f, &o.ors_filterstr );
an[0].an_desc = dli->dli_ad;
an[0].an_name = dli->dli_ad->ad_cname;
found = ds->ds_found;
{
SlapReply r = { REP_SEARCH };
(void)o.o_bd->be_search( &o, &r );
}
if ( found != ds->ds_found && nested )
dynlist_nestlink( op, ds );
}
if ( ds->ds_names != NULL ) {
@ -1468,6 +1805,24 @@ dynlist_search( Operation *op, SlapReply *rs )
sc->sc_cleanup = dynlist_search_cleanup;
sc->sc_next = op->o_callback;
op->o_callback = sc;
/* see if filter needs fixing */
if ( dlg->dlg_memberOf ) {
for ( dli = dlg->dlg_dli; dli; dli = dli->dli_next ) {
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_memberOf_ad ) {
/* if attribute is in filter, fix it */
if ( ad_infilter( dlm->dlm_memberOf_ad, op->ors_filter )) {
ds->ds_dli = dli;
ds->ds_dlm = dlm;
dynlist_fix_filter( op, dlm->dlm_memberOf_ad, ds );
}
}
}
}
}
} else {
op->o_tmpfree( sc, op->o_tmpmemctx );
}
@ -1951,6 +2306,12 @@ done_uri:;
dlmp->dlm_memberOf_ad = memberOf_ad;
dlmp->dlm_static_oc = static_oc;
dlmp->dlm_memberOf_nested = nested;
dlmp->dlm_member_oper = is_at_operational( member_ad->ad_type );
if ( memberOf_ad ) {
dlmp->dlm_memberOf_oper = is_at_operational( memberOf_ad->ad_type );
} else {
dlmp->dlm_memberOf_oper = 0;
}
dlmp->dlm_next = NULL;
if ( dlml != NULL )

View file

@ -386,3 +386,375 @@ dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
# Testing nested dynamic group functionality...
dn: cn=Dynamic List,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: Dynamic List
memberURL: ldap:///ou=People,dc=example,dc=com?cn,mail?sub?(objectClass=person
)
dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
objectClass: dgIdentityAux
cn: Dynamic List of Members
memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
dgIdentity: cn=Bjorn Jensen,ou=Information Technology DivisioN,ou=People,dc=ex
ample,dc=com
dgAuthz: {0}dn:cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,
dc=example,dc=com
member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
ple,dc=com
member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
e,dc=com
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
mple,dc=com
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
=com
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
dn: ou=Dynamic Lists,dc=example,dc=com
objectClass: organizationalUnit
ou: Dynamic Lists
dn: cn=Meta Group,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: Meta Group
memberURL: ldap:///ou=Dynamic Lists,dc=example,dc=com??sub?(description=Smith%
20family)
member: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dn: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: The Smiths
memberURL: ldap:///ou=People,dc=example,dc=com??sub?(sn=Smith)
description: Smith family
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dgMemberOf: cn=meta group,ou=dynamic lists,dc=example,dc=com
dn: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: Mark Elliot
cn: Mark A Elliot
sn: Elliot
uid: melliot
postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
homePostalAddress: 199 Outer Drive $ Ypsilanti, MI 48198
homePhone: +1 313 555 0388
drink: Gasoline
title: Director, UM Alumni Association
mail: melliot@mail.alumni.example.com
pager: +1 313 555 7671
facsimileTelephoneNumber: +1 313 555 7762
telephoneNumber: +1 313 555 4177
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
# Testing nested static group functionality...
dn: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=example,
dc=com
objectClass: OpenLDAPperson
cn: Barbara Jensen
cn: Babs Jensen
sn:: IEplbnNlbiA=
uid: bjensen
title: Mythical Manager, Research Systems
postalAddress: ITD Prod Dev & Deployment $ 535 W. William St. Room 4212 $ Anyt
own, MI 48103-4943
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
userPassword:: YmplbnNlbg==
mail: bjensen@mailgw.example.com
homePostalAddress: 123 Wesley $ Anytown, MI 48103
description: Mythical manager of the rsdd unix project
drink: water
homePhone: +1 313 555 2333
pager: +1 313 555 3233
facsimileTelephoneNumber: +1 313 555 2274
telephoneNumber: +1 313 555 9022
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=the jensens,ou=groups,dc=example,dc=com
dgMemberOf: cn=jjs,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
=com
objectClass: OpenLDAPperson
cn: Bjorn Jensen
cn: Biiff Jensen
sn: Jensen
uid: bjorn
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
seeAlso: cn=itd staff,ou=groups,dc=example,dc=com
userPassword:: Ympvcm4=
homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
drink: Iced Tea
description: Hiker, biker
title: Director, Embedded Systems
postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
mail: bjorn@mailgw.example.com
homePhone: +1 313 555 5444
pager: +1 313 555 4474
facsimileTelephoneNumber: +1 313 555 2177
telephoneNumber: +1 313 555 0355
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=the jensens,ou=groups,dc=example,dc=com
dgMemberOf: cn=jjs,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: Ursula Hampster
sn: Hampster
uid: uham
title: Secretary, UM Alumni Association
postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
homePostalAddress: 123 Anystreet $ Anytown, MI 48104
mail: uham@mail.alumni.example.com
homePhone: +1 313 555 8421
pager: +1 313 555 2844
facsimileTelephoneNumber: +1 313 555 9700
telephoneNumber: +1 313 555 5331
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dgMemberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=example
,dc=com
objectClass: OpenLDAPperson
cn: James A Jones 2
cn: James Jones
cn: Jim Jones
sn: Doe
uid: jjones
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
seeAlso: cn=itd staff,ou=groups,dc=example,dc=com
homePostalAddress: 933 Brooks $ Anytown, MI 48104
homePhone: +1 313 555 8838
title: Senior Manager, Information Technology Division
description: Not around very much
mail: jjones@mailgw.example.com
postalAddress: Info Tech Division $ 535 W William $ Anytown, MI 48103
pager: +1 313 555 2833
facsimileTelephoneNumber: +1 313 555 8688
telephoneNumber: +1 313 555 7334
dgMemberOf: cn=jjs,ou=groups,dc=example,dc=com
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: Jane Doe
cn: Jane Alverson
sn: Doe
uid: jdoe
title: Programmer Analyst, UM Alumni Association
postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
homePostalAddress: 123 Anystreet $ Anytown, MI 48104
drink: diet coke
description: Enthusiastic
mail: jdoe@woof.net
homePhone: +1 313 555 5445
pager: +1 313 555 1220
facsimileTelephoneNumber: +1 313 555 2311
telephoneNumber: +1 313 555 4774
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: John Doe
cn: Jonathon Doe
sn: Doe
uid: johnd
postalAddress: ITD $ 535 W. William $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
seeAlso: cn=itd staff,ou=groups,dc=example,dc=com
homePostalAddress: 912 East Bllvd $ Anytown, MI 48104
title: System Administrator, Information Technology Division
description: overworked!
mail: johnd@mailgw.example.com
homePhone: +1 313 555 3774
pager: +1 313 555 6573
facsimileTelephoneNumber: +1 313 555 4544
telephoneNumber: +1 313 555 9394
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: Jennifer Smith
cn: Jen Smith
sn: Smith
uid: jen
postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
drink: Sam Adams
homePostalAddress: 1000 Maple #44 $ Anytown, MI 48103
title: Telemarketer, UM Alumni Association
mail: jen@mail.alumni.example.com
homePhone: +1 313 555 2333
pager: +1 313 555 6442
facsimileTelephoneNumber: +1 313 555 2756
telephoneNumber: +1 313 555 8232
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=the smiths,ou=dynamic lists,dc=example,dc=com
dgMemberOf: cn=meta group,ou=dynamic lists,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dgMemberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
# Testing filtered nested memberOf functionality...
dn: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: Jennifer Smith
cn: Jen Smith
sn: Smith
uid: jen
postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
drink: Sam Adams
homePostalAddress: 1000 Maple #44 $ Anytown, MI 48103
title: Telemarketer, UM Alumni Association
mail: jen@mail.alumni.example.com
homePhone: +1 313 555 2333
pager: +1 313 555 6442
facsimileTelephoneNumber: +1 313 555 2756
telephoneNumber: +1 313 555 8232
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=the smiths,ou=dynamic lists,dc=example,dc=com
dgMemberOf: cn=meta group,ou=dynamic lists,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dgMemberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
dn: cn=Meta Group,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: Meta Group
memberURL: ldap:///ou=Dynamic Lists,dc=example,dc=com??sub?(description=Smith%
20family)
member: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dn: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: The Smiths
memberURL: ldap:///ou=People,dc=example,dc=com??sub?(sn=Smith)
description: Smith family
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dgMemberOf: cn=meta group,ou=dynamic lists,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
cn: Ursula Hampster
sn: Hampster
uid: uham
title: Secretary, UM Alumni Association
postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
homePostalAddress: 123 Anystreet $ Anytown, MI 48104
mail: uham@mail.alumni.example.com
homePhone: +1 313 555 8421
pager: +1 313 555 2844
facsimileTelephoneNumber: +1 313 555 9700
telephoneNumber: +1 313 555 5331
dgMemberOf: cn=all staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dgMemberOf: cn=alumni assoc staff,ou=groups,dc=example,dc=com
dgMemberOf: cn=dynamic list of members,ou=dynamic lists,dc=example,dc=com
# Testing filtered nested member functionality...
dn: cn=All Staff,ou=Groups,dc=example,dc=com
member: cn=Manager,dc=example,dc=com
member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
ple,dc=com
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
=com
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
mple,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
e,dc=com
owner: cn=Manager,dc=example,dc=com
cn: All Staff
description: Everyone in the sample data
objectClass: groupofnames
dn: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
member: cn=Manager,dc=example,dc=com
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
owner: cn=Manager,dc=example,dc=com
description: All Alumni Assoc Staff
cn: Alumni Assoc Staff
objectClass: groupofnames
dn: cn=Bonus Group,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Bonus Group
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Meta Group,ou=Dynamic Lists,dc=example,dc=com
member: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dn: cn=Dynamic List of Members,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
objectClass: dgIdentityAux
cn: Dynamic List of Members
memberURL: ldap:///ou=People,dc=example,dc=com??sub?(objectClass=person)
dgIdentity: cn=Bjorn Jensen,ou=Information Technology DivisioN,ou=People,dc=ex
ample,dc=com
dgAuthz: {0}dn:cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,
dc=example,dc=com
member: cn=Barbara Jensen,ou=Information Technology Division,ou=People,dc=exam
ple,dc=com
member: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=exampl
e,dc=com
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=James A Jones 2,ou=Information Technology Division,ou=People,dc=exa
mple,dc=com
member: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc
=com
member: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
dn: cn=Meta Group,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: Meta Group
memberURL: ldap:///ou=Dynamic Lists,dc=example,dc=com??sub?(description=Smith%
20family)
member: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com
dn: cn=The Smiths,ou=Dynamic Lists,dc=example,dc=com
objectClass: groupOfURLs
cn: The Smiths
memberURL: ldap:///ou=People,dc=example,dc=com??sub?(sn=Smith)
description: Smith family
member: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
dgMemberOf: cn=meta group,ou=dynamic lists,dc=example,dc=com
dgMemberOf: cn=bonus group,ou=groups,dc=example,dc=com

View file

@ -763,6 +763,179 @@ if test $RC != 0 ; then
exit $RC
fi
echo "Reconfiguring slapd..."
$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
$TESTOUT 2>&1 << EOMODS
version: 1
dn: olcOverlay={0}dynlist,olcDatabase={$DBIX}$BACKEND,cn=config
changetype: modify
delete: olcDynListAttrSet
olcDynListAttrSet: {0}
-
add: olcDynListAttrSet
olcDynListAttrSet: groupOfURLs memberURL member+dgMemberOf*
-
EOMODS
echo "==========================================================" >> $LOG1
echo "Adding a couple dynamic groups..."
$LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
> $TESTOUT 2>&1 << EOMODS
dn: cn=The Smiths,$LISTDN
objectClass: groupOfURLs
cn: The Smiths
memberURL: ldap:///ou=People,${BASEDN}??sub?(sn=Smith)
description: Smith family
dn: cn=Meta Group,$LISTDN
objectClass: groupOfURLs
cn: Meta Group
memberURL: ldap:///${LISTDN}??sub?(description=Smith%20family)
EOMODS
echo "Testing nested dynamic group functionality..."
echo "# Testing nested dynamic group functionality..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
'(objectclass=*)' '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
$LDAPSEARCH -S "" -b "ou=People,$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
'(cn=Mark Elliot)' '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Reconfiguring slapd..."
$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
$TESTOUT 2>&1 << EOMODS
version: 1
dn: olcOverlay={0}dynlist,olcDatabase={$DBIX}$BACKEND,cn=config
changetype: modify
delete: olcDynListAttrSet
olcDynListAttrSet: {0}
-
add: olcDynListAttrSet
olcDynListAttrSet: groupOfURLs memberURL member+dgMemberOf@groupOfNames*
olcDynListAttrSet: labeledURIObject labeledURI uniqueMember+seeAlso@groupOfUniqueNames
-
EOMODS
echo "==========================================================" >> $LOG1
echo "Adding a couple static groups..."
$LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
> $TESTOUT 2>&1 << EOMODS
dn: cn=The Jensens,ou=Groups,$BASEDN
objectClass: groupOfnames
cn: The Jensens
member: cn=Bjorn Jensen,ou=Information Technology DivisioN,ou=People,$BASEDN
member: cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,$BASEDN
dn: cn=JJs,ou=Groups,$BASEDN
objectClass: groupOfnames
cn: JJs
member: cn=James A Jones 1,ou=Alumni Association,ou=People,$BASEDN
member: cn=James A Jones 2,ou=Information Technology Division,ou=People,$BASEDN
member: cn=The Jensens,ou=Groups,$BASEDN
EOMODS
echo "Testing nested static group functionality..."
echo "# Testing nested static group functionality..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "ou=People,$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
'(sn=Jensen)' '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Adding another nested group..."
$LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
> $TESTOUT 2>&1 << EOMODS
dn: cn=Bonus Group,ou=Groups,$BASEDN
objectClass: groupOfnames
cn: Bonus Group
member: cn=Ursula Hampster,ou=Alumni Association,ou=People,$BASEDN
member: cn=Meta Group,$LISTDN
EOMODS
$LDAPSEARCH -S "" -b "ou=People,$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
'(sn=Hampster)' '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
$LDAPSEARCH -S "" -b "ou=People,$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
'(sn=Doe)' '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
$LDAPSEARCH -S "" -b "ou=People,$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
'(sn=Smith)' '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Testing filtered nested memberOf functionality..."
echo "# Testing filtered nested memberOf functionality..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
"(dgMemberOf=cn=bonus group,ou=groups,$BASEDN)" '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Testing filtered nested member functionality..."
echo "# Testing filtered nested member functionality..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
-D "$BABSDN" -w bjensen \
"(member=cn=Jennifer Smith,ou=Alumni Association,ou=People,$BASEDN)" '*' \
>> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
test $KILLSERVERS != no && kill -HUP $KILLPIDS
LDIF=$DYNLISTOUT