ITS#10161 Add nestgroup overlay

This commit is contained in:
Howard Chu 2024-01-26 17:22:16 +00:00 committed by Quanah Gibson-Mount
parent e62c5d80b1
commit ddd42a2af3
10 changed files with 2681 additions and 0 deletions

View File

@ -349,6 +349,7 @@ Overlays="accesslog \
dynlist \
homedir \
memberof \
nestgroup \
otp \
ppolicy \
proxycache \
@ -392,6 +393,8 @@ OL_ARG_ENABLE(homedir, [AS_HELP_STRING([--enable-homedir], [Home Directory Manag
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(memberof, [AS_HELP_STRING([--enable-memberof], [Reverse Group Membership overlay])],
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(nestgroup, [AS_HELP_STRING([--enable-nestgroup], [Nested Group overlay])],
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(otp, [AS_HELP_STRING([--enable-otp], [OTP 2-factor authentication overlay])],
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(ppolicy, [AS_HELP_STRING([--enable-ppolicy], [Password Policy overlay])],
@ -2867,6 +2870,17 @@ if test "$ol_enable_memberof" != no ; then
AC_DEFINE_UNQUOTED(SLAPD_OVER_MEMBEROF,$MFLAG,[define for Reverse Group Membership overlay])
fi
if test "$ol_enable_nestgroup" != no ; then
if test "$ol_enable_nestgroup" = mod ; then
MFLAG=SLAPD_MOD_DYNAMIC
SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS nestgroup.la"
else
MFLAG=SLAPD_MOD_STATIC
SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS nestgroup.o"
fi
AC_DEFINE_UNQUOTED(SLAPD_OVER_NESTGROUP,$MFLAG,[define for Nested Group overlay])
fi
if test "$ol_enable_otp" != no ; then
if test $ol_with_tls = no ; then
AC_MSG_ERROR([--enable-otp=$ol_enable_otp requires --with-tls])

View File

@ -0,0 +1,92 @@
.TH SLAPO-NESTGROUP 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" Copyright 2024 The OpenLDAP Foundation, All Rights Reserved.
.\" Copying restrictions apply. See the COPYRIGHT file.
.\" $OpenLDAP$
.SH NAME
slapo\-nestgroup \- Nested Group overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The
.B nestgroup
overlay to
.BR slapd (8)
supports evaluation of nested groups in Search operations. Support consists
of four possible features: inclusion of parent groups when searching with
(member=) filters, inclusion of child groups when searching with (memberOf=)
filters, expansion of child groups when returning member attributes, and
expansion of parent groups when returning memberOf attributes. Each of
these features may be enabled independently. By default, no features are
enabled, so this overlay does nothing unless explicitly enabled.
.SH CONFIGURATION
The config directives that are specific to the
.B nestgroup
overlay must be prefixed by
.BR nestgroup\- ,
to avoid potential conflicts with directives specific to the underlying
database or to other stacked overlays.
.TP
.B overlay nestgroup
This directive adds the nestgroup overlay to the current database; see
.BR slapd.conf (5)
for details.
.LP
The following
.B slapd.conf
configuration options are defined for the nestgroup overlay.
.TP
.BI nestgroup\-member \ <member-ad>
The value
.I <member-ad>
is the name of the attribute that contains the names of the members
in the group objects; it must be DN-valued.
It defaults to \fImember\fP.
.TP
.BI nestgroup\-memberof \ <memberof-ad>
The value
.I <memberof-ad>
is the name of the attribute that contains the names of the groups
an entry is member of; it must be DN-valued.
It defaults to \fImemberOf\fP.
.TP
.BI nestgroup\-base \ <dn>
The value
.I <dn>
specifies a subtree that contains group entries in the DIT. This
may be specified multiple times for multiple distinct subtrees.
It has no default and the overlay does no processing unless it is
explicitly configured.
.TP
.BI "nestgroup\-flags {" member-filter ", " memberof-filter ", " member-values ", " memberof-values "}"
This option specifies which features to enable in the overlay.
By default, nothing is enabled and the overlay is a no-op.
.LP
The nestgroup overlay may be used with any backend that provides standard
search functionality.
.SH FILES
.TP
ETCDIR/slapd.conf
default slapd configuration file
.SH SEE ALSO
.BR slapo\-dynlist (5),
.BR slapo\-memberof (5),
.BR slapd.conf (5),
.BR slapd\-config (5),
.BR slapd (8).
The
.BR slapo\-nestgroup (5)
overlay supports dynamic configuration via
.BR back-config .
.SH ACKNOWLEDGEMENTS
.P
This module was written in 2024 by Howard Chu of Symas Corporation.

View File

@ -285,6 +285,7 @@ static OidRec OidMacros[] = {
* OLcfgOv{Oc|At}:21 -> sssvlv
* OLcfgOv{Oc|At}:22 -> autoca
* OLcfgOv{Oc|At}:24 -> remoteauth
* OLcfgOv{Oc|At}:25 -> nestgroup
*/
/* alphabetical ordering */

View File

@ -24,6 +24,7 @@ SRCS = overlays.c \
dynlist.c \
homedir.c \
memberof.c \
nestgroup.c \
otp.c \
pcache.c \
collect.c \
@ -96,6 +97,9 @@ homedir.la : homedir.lo
memberof.la : memberof.lo
$(LTLINK_MOD) -module -o $@ memberof.lo version.lo $(LINK_LIBS)
nestgroup.la : nestgroup.lo
$(LTLINK_MOD) -module -o $@ nestgroup.lo version.lo $(LINK_LIBS)
otp.la : otp.lo
$(LTLINK_MOD) -module -o $@ otp.lo version.lo $(LINK_LIBS)

View File

@ -0,0 +1,909 @@
/* nestgroup.c - nested group overlay */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2024 The OpenLDAP Foundation.
* Copyright 2024 by Howard Chu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Howard Chu for inclusion in
* OpenLDAP Software.
*/
#include "portable.h"
#ifdef SLAPD_OVER_NESTGROUP
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "lutil.h"
#include "slap.h"
#include "slap-config.h"
/* This overlay dynamically constructs member and memberOf attributes
* for nested groups.
*/
#define SLAPD_MEMBEROF_ATTR "memberOf"
#define NG_MBR_VALUES 0x01
#define NG_MBR_FILTER 0x02
#define NG_MOF_VALUES 0x04
#define NG_MOF_FILTER 0x08
#define NG_NEGATED 0x10
static AttributeDescription *ad_member;
static AttributeDescription *ad_memberOf;
static slap_verbmasks nestgroup_flags[] = {
{ BER_BVC("member-values"), NG_MBR_VALUES },
{ BER_BVC("member-filter"), NG_MBR_FILTER },
{ BER_BVC("memberof-values"), NG_MOF_VALUES },
{ BER_BVC("memberof-filter"), NG_MOF_FILTER },
{ BER_BVNULL, 0 }
};
enum {
NG_MEMBER = 1,
NG_MEMBEROF,
NG_GROUPBASE,
NG_FLAGS
};
typedef struct nestgroup_info_t {
AttributeDescription *ngi_member;
AttributeDescription *ngi_memberOf;
BerVarray ngi_groupBase;
BerVarray ngi_ngroupBase;
int ngi_flags;
} nestgroup_info_t;
static int ngroup_cf( ConfigArgs *c )
{
slap_overinst *on = (slap_overinst *)c->bi;
nestgroup_info_t *ngi = (nestgroup_info_t *)on->on_bi.bi_private;
int rc = 1;
if ( c->op == SLAP_CONFIG_EMIT ) {
switch( c->type ) {
case NG_MEMBER:
if ( ngi->ngi_member ) {
value_add_one( &c->rvalue_vals, &ngi->ngi_member->ad_cname );
rc = 0;
}
break;
case NG_MEMBEROF:
if ( ngi->ngi_memberOf ) {
value_add_one( &c->rvalue_vals, &ngi->ngi_memberOf->ad_cname );
rc = 0;
}
break;
case NG_GROUPBASE:
if ( ngi->ngi_groupBase ) {
value_add( &c->rvalue_vals, ngi->ngi_groupBase );
value_add( &c->rvalue_nvals, ngi->ngi_ngroupBase );
rc = 0;
}
break;
case NG_FLAGS:
return mask_to_verbs( nestgroup_flags, ngi->ngi_flags, &c->rvalue_vals );
default:
break;
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) {
switch( c->type ) {
case NG_MEMBER:
ngi->ngi_member = ad_member;
rc = 0;
break;
case NG_MEMBEROF:
ngi->ngi_memberOf = ad_memberOf;
rc = 0;
break;
case NG_GROUPBASE:
if ( c->valx < 0 ) {
ber_bvarray_free( ngi->ngi_groupBase );
ber_bvarray_free( ngi->ngi_ngroupBase );
ngi->ngi_groupBase = NULL;
ngi->ngi_ngroupBase = NULL;
} else {
int i = c->valx;
ch_free( ngi->ngi_groupBase[i].bv_val );
ch_free( ngi->ngi_ngroupBase[i].bv_val );
do {
ngi->ngi_groupBase[i] = ngi->ngi_groupBase[i+1];
ngi->ngi_ngroupBase[i] = ngi->ngi_ngroupBase[i+1];
i++;
} while ( !BER_BVISNULL( &ngi->ngi_groupBase[i] ));
}
rc = 0;
break;
case NG_FLAGS:
if ( !c->line ) {
ngi->ngi_flags = 0;
} else {
int i = verb_to_mask( c->line, nestgroup_flags );
ngi->ngi_flags &= ~nestgroup_flags[i].mask;
}
rc = 0;
break;
default:
break;
}
return rc;
}
switch( c->type ) {
case NG_MEMBER:
if ( !is_at_syntax( c->value_ad->ad_type, SLAPD_DN_SYNTAX ) &&
!is_at_syntax( c->value_ad->ad_type, SLAPD_NAMEUID_SYNTAX )) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"member attribute=\"%s\" must use DN (%s) or NAMEUID (%s) syntax",
c->argv[1], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
"%s: %s\n", c->log, c->cr_msg );
return ARG_BAD_CONF;
}
ngi->ngi_member = c->value_ad;
rc = 0;
break;
case NG_MEMBEROF:
if ( !is_at_syntax( c->value_ad->ad_type, SLAPD_DN_SYNTAX ) &&
!is_at_syntax( c->value_ad->ad_type, SLAPD_NAMEUID_SYNTAX )) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"memberOf attribute=\"%s\" must use DN (%s) or NAMEUID (%s) syntax",
c->argv[1], SLAPD_DN_SYNTAX, SLAPD_NAMEUID_SYNTAX );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
"%s: %s\n", c->log, c->cr_msg );
return ARG_BAD_CONF;
}
ngi->ngi_memberOf = c->value_ad;
rc = 0;
break;
case NG_GROUPBASE:
ber_bvarray_add( &ngi->ngi_groupBase, &c->value_dn );
ber_bvarray_add( &ngi->ngi_ngroupBase, &c->value_ndn );
rc = 0;
break;
case NG_FLAGS: {
slap_mask_t flags = 0;
int i;
if ( c->op != SLAP_CONFIG_ADD && c->argc > 2 ) {
/* We wouldn't know how to delete these values later */
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"Please insert multiple names as separate %s values",
c->argv[0] );
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE,
"%s: %s\n", c->log, c->cr_msg );
rc = LDAP_INVALID_SYNTAX;
break;
}
i = verbs_to_mask( c->argc, c->argv, nestgroup_flags, &flags );
if ( i ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown option", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
c->log, c->cr_msg, c->argv[i]);
return(1);
}
ngi->ngi_flags |= flags;
rc = 0;
break; }
default:
break;
}
return rc;
}
static ConfigTable ngroupcfg[] = {
{ "nestgroup-member", "member-ad", 2, 2, 0,
ARG_MAGIC|ARG_ATDESC|NG_MEMBER, ngroup_cf,
"( OLcfgOvAt:25.1 NAME 'olcNestGroupMember' "
"EQUALITY caseIgnoreMatch "
"DESC 'Member attribute' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "nestgroup-memberof", "memberOf-ad", 2, 2, 0,
ARG_MAGIC|ARG_ATDESC|NG_MEMBEROF, ngroup_cf,
"( OLcfgOvAt:25.2 NAME 'olcNestGroupMemberOf' "
"EQUALITY caseIgnoreMatch "
"DESC 'MemberOf attribute' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "nestgroup-base", "dn", 2, 2, 0,
ARG_DN|ARG_QUOTE|ARG_MAGIC|NG_GROUPBASE, ngroup_cf,
"( OLcfgOvAt:25.3 NAME 'olcNestGroupBase' "
"EQUALITY distinguishedNameMatch "
"DESC 'Base[s] of group subtree[s]' "
"SYNTAX OMsDN )", NULL, NULL },
{ "nestgroup-flags", "options", 2, 0, 0,
ARG_MAGIC|NG_FLAGS, ngroup_cf,
"( OLcfgOvAt:25.4 NAME 'olcNestGroupFlags' "
"EQUALITY caseIgnoreMatch "
"DESC 'Features to use' "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
static ConfigOCs ngroupocs[] = {
{ "( OLcfgOvOc:25.1 "
"NAME 'olcNestGroupConfig' "
"DESC 'Nested Group configuration' "
"SUP olcOverlayConfig "
"MAY ( olcNestGroupMember $ olcNestGroupMemberOf $ "
" olcNestGroupBase $ olcNestGroupFlags ) ) ",
Cft_Overlay, ngroupcfg },
{ NULL, 0, NULL }
};
typedef struct nestgroup_filterinst_t {
Filter *nf_f;
Filter *nf_new;
Entry *nf_e;
} nestgroup_filterinst_t;
/* Record occurrences of ad in filter. Ignore in negated filters. */
static void
nestgroup_filter_instances( Operation *op, AttributeDescription *ad, Filter *f, int not,
int *nfn, nestgroup_filterinst_t **nfp, int *negated )
{
if ( !f )
return;
switch( f->f_choice & SLAPD_FILTER_MASK ) {
case LDAP_FILTER_EQUALITY:
if ( f->f_av_desc == ad ) {
if ( not ) {
*negated = 1;
} else {
nestgroup_filterinst_t *nf = *nfp;
int n = *nfn;
nf = op->o_tmprealloc( nf, (n + 1) * sizeof(nestgroup_filterinst_t), op->o_tmpmemctx );
nf[n].nf_f = f;
nf[n].nf_new = NULL;
nf[n++].nf_e = NULL;
*nfp = nf;
*nfn = n;
}
}
break;
case SLAPD_FILTER_COMPUTED:
case LDAP_FILTER_PRESENT:
case LDAP_FILTER_GE:
case LDAP_FILTER_LE:
case LDAP_FILTER_APPROX:
case LDAP_FILTER_SUBSTRINGS:
case LDAP_FILTER_EXT:
break;
case LDAP_FILTER_NOT: not ^= 1;
/* FALLTHRU */
case LDAP_FILTER_AND:
case LDAP_FILTER_OR:
for ( f = f->f_list; f; f = f->f_next )
nestgroup_filter_instances( op, ad, f, not, nfn, nfp, negated );
}
}
static int
nestgroup_check_needed( Operation *op, int attrflags, AttributeDescription *ad )
{
if ( is_at_operational( ad->ad_type )) {
if ( SLAP_OPATTRS( attrflags ))
return 1;
} else {
if ( SLAP_USERATTRS( attrflags ))
return 1;
}
return ( ad_inlist( ad, op->ors_attrs ));
}
typedef struct DNpair {
struct berval dp_ndn;
struct berval dp_dn;
struct DNpair *dp_next;
int dp_flag;
} DNpair;
typedef struct gdn_info {
TAvlnode *gi_DNs;
DNpair *gi_DNlist;
nestgroup_info_t *gi_ngi;
int gi_numDNs;
int gi_saveDN;
Attribute *gi_merge;
} gdn_info;
static int
nestgroup_dncmp( const void *v1, const void *v2 )
{
return ber_bvcmp((const struct berval *)v1, (const struct berval *)v2);
}
static int
nestgroup_gotDNresp( Operation *op, SlapReply *rs )
{
if ( rs->sr_type == REP_SEARCH ) {
gdn_info *gi = (gdn_info *)(op->o_callback+1);
DNpair *dp = op->o_tmpalloc( sizeof(DNpair), op->o_tmpmemctx );
dp->dp_ndn = rs->sr_entry->e_nname;
if ( ldap_tavl_insert( &gi->gi_DNs, dp, nestgroup_dncmp, ldap_avl_dup_error )) {
op->o_tmpfree( dp, op->o_tmpmemctx );
} else {
ber_dupbv_x( &dp->dp_ndn, &rs->sr_entry->e_nname, op->o_tmpmemctx );
if ( gi->gi_saveDN )
ber_dupbv_x( &dp->dp_dn, &rs->sr_entry->e_name, op->o_tmpmemctx );
gi->gi_numDNs++;
dp->dp_next = gi->gi_DNlist;
dp->dp_flag = 0;
gi->gi_DNlist = dp;
}
}
return 0;
}
static void
nestgroup_get_parentDNs( Operation *op, struct berval *ndn )
{
SlapReply r = { REP_SEARCH };
gdn_info *gi = (gdn_info *)(op->o_callback+1);
nestgroup_info_t *ngi = gi->gi_ngi;
int i;
op->ors_filter->f_av_value = *ndn;
for ( i=0; !BER_BVISEMPTY( &ngi->ngi_ngroupBase[i] ); i++ ) {
op->o_req_dn = ngi->ngi_groupBase[i];
op->o_req_ndn = ngi->ngi_ngroupBase[i];
op->o_bd->be_search( op, &r );
}
gi->gi_numDNs = 0; /* ignore first count, that's just the original member= result set */
while ( gi->gi_DNlist ) {
int prevnum;
DNpair *dp = gi->gi_DNlist;
gi->gi_DNlist = NULL;
for ( ; dp; dp=dp->dp_next ) {
op->ors_filter->f_av_value = dp->dp_ndn;
prevnum = gi->gi_numDNs;
for ( i=0; !BER_BVISEMPTY( &ngi->ngi_ngroupBase[i] ); i++ ) {
op->o_req_dn = ngi->ngi_groupBase[i];
op->o_req_ndn = ngi->ngi_ngroupBase[i];
op->o_bd->be_search( op, &r );
}
if ( gi->gi_numDNs > prevnum )
dp->dp_flag = 1; /* this group had a parent */
}
}
}
static void
nestgroup_memberFilter( Operation *op, int mbr_nf, nestgroup_filterinst_t *mbr_f )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
nestgroup_info_t *ngi = on->on_bi.bi_private;
AttributeDescription *ad = mbr_f[0].nf_f->f_av_desc;
slap_callback *sc;
gdn_info *gi;
Filter mf;
AttributeAssertion mava;
Operation o = *op;
int i;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
sc = op->o_tmpcalloc( 1, sizeof(slap_callback) + sizeof(gdn_info), op->o_tmpmemctx);
gi = (gdn_info *)(sc+1);
gi->gi_ngi = ngi;
o.o_callback = sc;
sc->sc_response = nestgroup_gotDNresp;
o.ors_attrs = slap_anlist_no_attrs;
mf.f_choice = LDAP_FILTER_EQUALITY;
mf.f_ava = &mava;
mf.f_av_desc = ad;
mf.f_next = NULL;
o.ors_scope = LDAP_SCOPE_SUBTREE;
o.ors_deref = LDAP_DEREF_NEVER;
o.ors_limit = NULL;
o.ors_tlimit = SLAP_NO_LIMIT;
o.ors_slimit = SLAP_NO_LIMIT;
o.ors_filter = &mf;
o.o_bd->bd_info = (BackendInfo *)on->on_info;
for ( i=0; i<mbr_nf; i++ ) {
gi->gi_DNs = NULL;
gi->gi_numDNs = 0;
nestgroup_get_parentDNs( &o, &mbr_f[i].nf_f->f_av_value );
if ( gi->gi_numDNs ) {
int j;
Filter *f, *nf;
TAvlnode *t;
DNpair *dp;
f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
f->f_next = NULL;
t = ldap_tavl_end( gi->gi_DNs, TAVL_DIR_RIGHT );
do {
dp = t->avl_data;
if ( dp->dp_flag ) {
nf = f;
nf->f_ava = op->o_tmpcalloc( 1, sizeof( AttributeAssertion ), op->o_tmpmemctx );
nf->f_choice = LDAP_FILTER_EQUALITY;
nf->f_av_desc = ad;
nf->f_av_value = dp->dp_ndn;
f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
f->f_next = nf;
}
t = ldap_tavl_next( t, TAVL_DIR_LEFT );
op->o_tmpfree( dp, op->o_tmpmemctx );
} while ( t );
ldap_tavl_free( gi->gi_DNs, NULL );
f->f_choice = LDAP_FILTER_EQUALITY;
f->f_ava = mbr_f[i].nf_f->f_ava;
mbr_f[i].nf_new = f;
}
}
o.o_bd->bd_info = (BackendInfo *)on->on_info;
op->o_tmpfree( sc, op->o_tmpmemctx );
}
static void
nestgroup_addUnique( Operation *op, Attribute *old, Attribute *new )
{
/* strip out any duplicates from new before adding */
struct berval *bv, *nbv;
int i, j, flags;
bv = op->o_tmpalloc( (new->a_numvals + 1) * 2 * sizeof(struct berval), op->o_tmpmemctx );
nbv = bv + new->a_numvals+1;
flags = SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH|SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
for (i=0,j=0; i<new->a_numvals; i++) {
int rc = attr_valfind( old, flags, &new->a_nvals[i], NULL, NULL );
if ( rc ) {
bv[j] = new->a_vals[i];
nbv[j++] = new->a_nvals[i];
}
}
BER_BVZERO( &bv[j] );
BER_BVZERO( &nbv[j] );
attr_valadd( old, bv, nbv, j );
op->o_tmpfree( bv, op->o_tmpmemctx );
}
static void
nestgroup_get_childDNs( Operation *op, slap_overinst *on, gdn_info *gi, struct berval *ndn )
{
nestgroup_info_t *ngi = on->on_bi.bi_private;
Entry *e;
Attribute *a;
if ( overlay_entry_get_ov( op, ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL )
return;
a = attr_find( e->e_attrs, ngi->ngi_member );
if ( a ) {
int i, j;
for (i = 0; i<a->a_numvals; i++ ) {
/* record all group entries */
for (j = 0; !BER_BVISEMPTY( &ngi->ngi_groupBase[j] ); j++) {
if ( dnIsSuffix( &a->a_nvals[i], &ngi->ngi_ngroupBase[j] )) {
DNpair *dp = op->o_tmpalloc( sizeof(DNpair), op->o_tmpmemctx );
dp->dp_ndn = a->a_nvals[i];
if ( ldap_tavl_insert( &gi->gi_DNs, dp, nestgroup_dncmp, ldap_avl_dup_error )) {
op->o_tmpfree( dp, op->o_tmpmemctx );
} else {
ber_dupbv_x( &dp->dp_ndn, &a->a_nvals[i], op->o_tmpmemctx );
gi->gi_numDNs++;
dp->dp_next = gi->gi_DNlist;
gi->gi_DNlist = dp;
}
break;
}
}
}
if ( gi->gi_merge ) {
nestgroup_addUnique( op, gi->gi_merge, a );
}
}
overlay_entry_release_ov( op, e, 0, on );
}
static void
nestgroup_memberOfFilter( Operation *op, int mof_nf, nestgroup_filterinst_t *mof_f )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
AttributeDescription *ad = mof_f[0].nf_f->f_av_desc;
gdn_info gi = {0};
int i;
for ( i=0; i<mof_nf; i++ ) {
gi.gi_DNs = NULL;
gi.gi_numDNs = 0;
nestgroup_get_childDNs( op, on, &gi, &mof_f[i].nf_f->f_av_value );
while ( gi.gi_DNlist ) {
DNpair *dp = gi.gi_DNlist;
gi.gi_DNlist = NULL;
for ( ; dp; dp=dp->dp_next ) {
nestgroup_get_childDNs( op, on, &gi, &dp->dp_ndn );
}
}
if ( gi.gi_numDNs ) {
int j;
Filter *f, *nf;
TAvlnode *t;
DNpair *dp;
f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
f->f_next = NULL;
t = ldap_tavl_end( gi.gi_DNs, TAVL_DIR_RIGHT );
do {
dp = t->avl_data;
nf = f;
nf->f_ava = op->o_tmpcalloc( 1, sizeof( AttributeAssertion ), op->o_tmpmemctx );
nf->f_choice = LDAP_FILTER_EQUALITY;
nf->f_av_desc = ad;
nf->f_av_value = dp->dp_ndn;
f = op->o_tmpalloc( sizeof(Filter), op->o_tmpmemctx );
f->f_next = nf;
t = ldap_tavl_next( t, TAVL_DIR_LEFT );
op->o_tmpfree( dp, op->o_tmpmemctx );
} while ( t );
ldap_tavl_free( gi.gi_DNs, NULL );
f->f_choice = LDAP_FILTER_EQUALITY;
f->f_ava = mof_f[i].nf_f->f_ava;
mof_f[i].nf_new = f;
}
}
}
static void
nestgroup_memberOfVals( Operation *op, slap_overinst *on, Attribute *a )
{
nestgroup_info_t *ngi = on->on_bi.bi_private;
Operation o = *op;
slap_callback *sc;
gdn_info *gi;
Filter mf;
AttributeAssertion mava;
int i;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
sc = op->o_tmpcalloc( 1, sizeof(slap_callback) + sizeof(gdn_info), op->o_tmpmemctx);
gi = (gdn_info *)(sc+1);
gi->gi_ngi = ngi;
o.o_callback = sc;
sc->sc_response = nestgroup_gotDNresp;
o.ors_attrs = slap_anlist_no_attrs;
mf.f_choice = LDAP_FILTER_EQUALITY;
mf.f_ava = &mava;
mf.f_av_desc = ngi->ngi_member;
mf.f_next = NULL;
o.ors_filter = &mf;
o.ors_scope = LDAP_SCOPE_SUBTREE;
o.ors_deref = LDAP_DEREF_NEVER;
o.ors_limit = NULL;
o.ors_tlimit = SLAP_NO_LIMIT;
o.ors_slimit = SLAP_NO_LIMIT;
o.o_bd->bd_info = (BackendInfo *)on->on_info;
gi->gi_saveDN = 1;
for ( i=0; i<a->a_numvals; i++ ) {
nestgroup_get_parentDNs( &o, &a->a_nvals[i] );
while ( gi->gi_DNlist ) {
DNpair *dp = gi->gi_DNlist;
gi->gi_DNlist = NULL;
for ( ; dp; dp=dp->dp_next ) {
nestgroup_get_parentDNs( &o, &dp->dp_ndn );
}
}
}
if ( gi->gi_DNs ) {
TAvlnode *p = ldap_tavl_end( gi->gi_DNs, TAVL_DIR_LEFT );
int flags = SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH|SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH;
do {
DNpair *dp = p->avl_data;
int rc = attr_valfind( a, flags, &dp->dp_ndn, NULL, NULL );
if ( rc )
attr_valadd( a, &dp->dp_dn, &dp->dp_ndn, 1 );
op->o_tmpfree( dp->dp_dn.bv_val, op->o_tmpmemctx );
op->o_tmpfree( dp->dp_ndn.bv_val, op->o_tmpmemctx );
op->o_tmpfree( dp, op->o_tmpmemctx );
p = ldap_tavl_next( p, TAVL_DIR_RIGHT );
} while ( p );
ldap_tavl_free( gi->gi_DNs, NULL );
}
o.o_bd->bd_info = (BackendInfo *)on->on_info;
op->o_tmpfree( sc, op->o_tmpmemctx );
}
typedef struct nestgroup_cbinfo {
slap_overinst *nc_on;
int nc_needed;
} nestgroup_cbinfo;
static int
nestgroup_searchresp( Operation *op, SlapReply *rs )
{
if (rs->sr_type == REP_SEARCH ) {
nestgroup_cbinfo *nc = op->o_callback->sc_private;
slap_overinst *on = nc->nc_on;
nestgroup_info_t *ngi = on->on_bi.bi_private;
Attribute *a;
if ( nc->nc_needed & NG_MBR_VALUES ) {
a = attr_find( rs->sr_entry->e_attrs, ngi->ngi_member );
if ( a ) {
gdn_info gi = {0};
int i, j;
if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) {
Entry *e = entry_dup( rs->sr_entry );
rs_replace_entry( op, rs, on, e );
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
a = attr_find( e->e_attrs, ngi->ngi_member );
}
gi.gi_merge = a;
for ( i=0; i<a->a_numvals; i++ ) {
for ( j=0; !BER_BVISEMPTY( &ngi->ngi_ngroupBase[j] ); j++ ) {
if ( dnIsSuffix( &a->a_nvals[i], &ngi->ngi_ngroupBase[j] )) {
nestgroup_get_childDNs( op, on, &gi, &a->a_nvals[i] );
while ( gi.gi_DNlist ) {
DNpair *dp = gi.gi_DNlist;
gi.gi_DNlist = NULL;
for ( ; dp; dp=dp->dp_next ) {
nestgroup_get_childDNs( op, on, &gi, &dp->dp_ndn );
}
}
break;
}
}
}
if ( gi.gi_numDNs ) {
TAvlnode *p = ldap_tavl_end( gi.gi_DNs, TAVL_DIR_LEFT );
do {
DNpair *dp = p->avl_data;
op->o_tmpfree( dp->dp_ndn.bv_val, op->o_tmpmemctx );
op->o_tmpfree( dp, op->o_tmpmemctx );
p = ldap_tavl_next( p, TAVL_DIR_RIGHT );
} while ( p );
ldap_tavl_free( gi.gi_DNs, NULL );
}
}
}
if ( nc->nc_needed & NG_MOF_VALUES ) {
a = attr_find( rs->sr_entry->e_attrs, ngi->ngi_memberOf );
if ( a ) {
if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) {
Entry *e = entry_dup( rs->sr_entry );
rs_replace_entry( op, rs, on, e );
rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
a = attr_find( e->e_attrs, ngi->ngi_memberOf );
}
nestgroup_memberOfVals( op, on, a );
}
}
if (( nc->nc_needed & NG_NEGATED ) &&
test_filter( op, rs->sr_entry, op->ors_filter ) != LDAP_COMPARE_TRUE )
return 0;
}
return SLAP_CB_CONTINUE;
}
static int
nestgroup_op_search( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
nestgroup_info_t *ngi = on->on_bi.bi_private;
int mbr_nf = 0, mof_nf = 0, negated = 0;
nestgroup_filterinst_t *mbr_f = NULL, *mof_f = NULL;
if ( get_manageDSAit( op ))
return SLAP_CB_CONTINUE;
/* groupBase must be explicitly configured */
if ( !ngi->ngi_ngroupBase )
return SLAP_CB_CONTINUE;
/* handle attrs in filter */
if ( ngi->ngi_flags & NG_MBR_FILTER ) {
nestgroup_filter_instances( op, ngi->ngi_member, op->ors_filter, 0, &mbr_nf, &mbr_f, &negated );
if ( mbr_nf ) {
/* find member=(parent groups) */
nestgroup_memberFilter( op, mbr_nf, mbr_f );
}
}
if ( ngi->ngi_flags & NG_MOF_FILTER ) {
nestgroup_filter_instances( op, ngi->ngi_memberOf, op->ors_filter, 0, &mof_nf, &mof_f, &negated );
if ( mof_nf ) {
/* find memberOf=(child groups) */
nestgroup_memberOfFilter( op, mof_nf, mof_f );
}
}
if ( mbr_nf ) {
int i;
for ( i=0; i<mbr_nf; i++ ) {
if ( mbr_f[i].nf_new ) {
mbr_f[i].nf_f->f_choice = LDAP_FILTER_OR;
mbr_f[i].nf_f->f_list = mbr_f[i].nf_new;
}
}
op->o_tmpfree( mbr_f, op->o_tmpmemctx );
}
if ( mof_nf ) {
int i;
for ( i=0; i<mof_nf; i++ ) {
if ( mof_f[i].nf_new ) {
mof_f[i].nf_f->f_choice = LDAP_FILTER_OR;
mof_f[i].nf_f->f_list = mof_f[i].nf_new;
}
}
op->o_tmpfree( mof_f, op->o_tmpmemctx );
}
if ( ngi->ngi_flags & ( NG_MBR_VALUES|NG_MOF_VALUES )) {
/* check for attrs in attrlist */
int attrflags = slap_attr_flags( op->ors_attrs );
int needed = 0;
if (( ngi->ngi_flags & NG_MBR_VALUES ) &&
nestgroup_check_needed( op, attrflags, ngi->ngi_member )) {
/* collect all members from child groups */
needed |= NG_MBR_VALUES;
}
if (( ngi->ngi_flags & NG_MOF_VALUES ) &&
nestgroup_check_needed( op, attrflags, ngi->ngi_memberOf )) {
/* collect DNs of all parent groups */
needed |= NG_MOF_VALUES;
}
if ( needed ) {
nestgroup_cbinfo *nc;
slap_callback *sc = op->o_tmpcalloc( 1, sizeof(slap_callback)+sizeof(nestgroup_cbinfo), op->o_tmpmemctx );
nc = (nestgroup_cbinfo *)(sc+1);
sc->sc_private = nc;
nc->nc_needed = needed;
nc->nc_on = on;
sc->sc_response = nestgroup_searchresp;
sc->sc_next = op->o_callback;
op->o_callback = sc;
if ( negated ) nc->nc_needed |= NG_NEGATED;
}
}
return SLAP_CB_CONTINUE;
}
static int
nestgroup_db_init(
BackendDB *be,
ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
nestgroup_info_t *ngi;
int rc;
const char *text = NULL;
ngi = (nestgroup_info_t *)ch_calloc( 1, sizeof( *ngi ));
on->on_bi.bi_private = ngi;
if ( !ad_memberOf ) {
rc = slap_str2ad( SLAPD_MEMBEROF_ATTR, &ad_memberOf, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "nestgroup_db_init: "
"unable to find attribute=\"%s\": %s (%d)\n",
SLAPD_MEMBEROF_ATTR, text, rc );
return rc;
}
}
if ( !ad_member ) {
rc = slap_str2ad( SLAPD_GROUP_ATTR, &ad_member, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "nestgroup_db_init: "
"unable to find attribute=\"%s\": %s (%d)\n",
SLAPD_GROUP_ATTR, text, rc );
return rc;
}
}
return 0;
}
static int
nestgroup_db_open(
BackendDB *be,
ConfigReply *cr)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
nestgroup_info_t *ngi = on->on_bi.bi_private;
if ( !ngi->ngi_member )
ngi->ngi_member = ad_member;
if ( !ngi->ngi_memberOf )
ngi->ngi_memberOf = ad_memberOf;
return 0;
}
static int
nestgroup_db_destroy(
BackendDB *be,
ConfigReply *cr
)
{
slap_overinst *on = (slap_overinst *) be->bd_info;
nestgroup_info_t *ngi = on->on_bi.bi_private;
ber_bvarray_free( ngi->ngi_groupBase );
ber_bvarray_free( ngi->ngi_ngroupBase );
ch_free( ngi );
return 0;
}
static slap_overinst nestgroup;
/* This overlay is set up for dynamic loading via moduleload. For static
* configuration, you'll need to arrange for the slap_overinst to be
* initialized and registered by some other function inside slapd.
*/
int nestgroup_initialize() {
int code;
code = register_at(
"( 1.2.840.113556.1.2.102 "
"NAME 'memberOf' "
"DESC 'Group that the entry belongs to' "
"SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' "
"EQUALITY distinguishedNameMatch " /* added */
"USAGE dSAOperation " /* added; questioned */
"NO-USER-MODIFICATION " /* added */
"X-ORIGIN 'iPlanet Delegated Administrator' )",
&ad_memberOf, 0 );
if ( code && code != SLAP_SCHERR_ATTR_DUP ) {
Debug( LDAP_DEBUG_ANY,
"nestgroup_initialize: register_at (memberOf) failed\n" );
return code;
}
nestgroup.on_bi.bi_type = "nestgroup";
nestgroup.on_bi.bi_db_init = nestgroup_db_init;
nestgroup.on_bi.bi_db_open = nestgroup_db_open;
nestgroup.on_bi.bi_db_destroy = nestgroup_db_destroy;
nestgroup.on_bi.bi_op_search = nestgroup_op_search;
/* nestgroup.on_bi.bi_op_compare = nestgroup_op_compare; */
nestgroup.on_bi.bi_cf_ocs = ngroupocs;
code = config_register_schema( ngroupcfg, ngroupocs );
if ( code ) return code;
return overlay_register( &nestgroup );
}
#if SLAPD_OVER_NESTGROUP == SLAPD_MOD_DYNAMIC
int
init_module( int argc, char *argv[] )
{
return nestgroup_initialize();
}
#endif
#endif /* defined(SLAPD_OVER_NESTGROUP) */

389
tests/data/nestgroup.out.1 Normal file
View File

@ -0,0 +1,389 @@
# Search the entire database...
dn: cn=A-M,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=Baby Herman,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Baby Herman
sn: Herman
dn: cn=Bugs Bunny,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Bugs Bunny
sn: Bunny
dn: cn=Daffy Duck,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Daffy Duck
sn: Duck
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
dn: cn=Elmer Fudd,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Elmer Fudd
sn: Fudd
dn: cn=Endless Loop,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Endless Loop
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example, Inc.
dc: example
dn: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Foghorn Leghorn
sn: Leghorn
dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups
dn: cn=Humans,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Humans
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: cn=Jessica Rabbit,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Jessica Rabbit
sn: Rabbit
dn: cn=Leporidae,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
dn: cn=Looney Tunes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
dn: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Loop, Endless
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: cn=Mixer1,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer1
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
dn: cn=Mixer2,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer2
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
dn: cn=Mixer3,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer3
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Porky Pig,ou=People,dc=example,dc=com
dn: cn=Mixer4,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer4
member: cn=Mixer1,ou=Groups,dc=example,dc=com
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
dn: cn=Mixer5,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer5
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Mixer3,ou=Groups,dc=example,dc=com
member: cn=A-M,ou=Groups,dc=example,dc=com
dn: cn=N-Z,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: N-Z
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People
dn: cn=Porky Pig,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
dn: cn=Rabbits,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Rabbits
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=Road Runner,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Road Runner
sn: Runner
dn: cn=Roger Rabbit,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Roger Rabbit
sn: Rabbit
dn: cn=Tweety Bird,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Tweety Bird
sn: Bird
dn: cn=Wile E. Coyote,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Wile E. Coyote
sn: Coyote
dn: cn=Yosemite Sam,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Yosemite Sam
sn: Sam
# Search for member=cn=Bugs Bunny...
dn: cn=A-M,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=Leporidae,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
dn: cn=Looney Tunes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
# Re-search for nested member=cn=Bugs Bunny...
dn: cn=A-M,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=Leporidae,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
dn: cn=Looney Tunes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
dn: cn=Mixer1,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer1
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
dn: cn=Mixer4,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer4
member: cn=Mixer1,ou=Groups,dc=example,dc=com
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
dn: cn=Mixer5,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer5
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Mixer3,ou=Groups,dc=example,dc=com
member: cn=A-M,ou=Groups,dc=example,dc=com
# Search the expanded groups...
dn: cn=A-M,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
dn: cn=Endless Loop,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Endless Loop
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups
dn: cn=Humans,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Humans
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: cn=Leporidae,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=Looney Tunes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
dn: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Loop, Endless
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Endless Loop,ou=Groups,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: cn=Mixer1,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer1
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
dn: cn=Mixer2,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer2
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: cn=Mixer3,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer3
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
dn: cn=Mixer4,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer4
member: cn=Mixer1,ou=Groups,dc=example,dc=com
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: cn=Mixer5,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer5
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Mixer3,ou=Groups,dc=example,dc=com
member: cn=A-M,ou=Groups,dc=example,dc=com
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=N-Z,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: N-Z
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: cn=Rabbits,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Rabbits
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com

606
tests/data/nestgroup.out.2 Normal file
View File

@ -0,0 +1,606 @@
# Re-search the entire database after adding memberof configuration...
dn: cn=A-M,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Baby Herman,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Baby Herman
sn: Herman
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer2,ou=Groups,dc=example,dc=com
dn: cn=Bugs Bunny,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Bugs Bunny
sn: Bunny
memberOf: cn=Leporidae,ou=Groups,dc=example,dc=com
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
dn: cn=Daffy Duck,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Daffy Duck
sn: Duck
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
dn: cn=Elmer Fudd,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Elmer Fudd
sn: Fudd
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Humans,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
dn: cn=Endless Loop,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Endless Loop
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Endless Loop,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example, Inc.
dc: example
dn: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Foghorn Leghorn
sn: Leghorn
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups
dn: cn=Humans,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Humans
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
memberOf: cn=Mixer2,ou=Groups,dc=example,dc=com
dn: cn=Jessica Rabbit,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Jessica Rabbit
sn: Rabbit
memberOf: cn=Rabbits,ou=Groups,dc=example,dc=com
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
dn: cn=Leporidae,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
dn: cn=Looney Tunes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
dn: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Loop, Endless
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Endless Loop,ou=Groups,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: cn=Mixer1,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer1
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
dn: cn=Mixer2,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer2
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Mixer3,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer3
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Mixer4,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer4
member: cn=Mixer1,ou=Groups,dc=example,dc=com
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: cn=Mixer5,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer5
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Mixer3,ou=Groups,dc=example,dc=com
member: cn=A-M,ou=Groups,dc=example,dc=com
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
dn: cn=N-Z,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: N-Z
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People
dn: cn=Porky Pig,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
dn: cn=Rabbits,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Rabbits
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
memberOf: cn=Leporidae,ou=Groups,dc=example,dc=com
dn: cn=Road Runner,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Road Runner
sn: Runner
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: cn=Roger Rabbit,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Roger Rabbit
sn: Rabbit
memberOf: cn=Rabbits,ou=Groups,dc=example,dc=com
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
dn: cn=Tweety Bird,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Tweety Bird
sn: Bird
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
dn: cn=Wile E. Coyote,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Wile E. Coyote
sn: Coyote
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: cn=Yosemite Sam,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Yosemite Sam
sn: Sam
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Humans,ou=Groups,dc=example,dc=com
# Search for memberOf=cn=Mixer3...
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
dn: cn=Porky Pig,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
# Re-search for memberOf=cn=Mixer3 with filter nesting...
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
dn: cn=Porky Pig,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
dn: cn=Road Runner,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Road Runner
sn: Runner
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: cn=Wile E. Coyote,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Wile E. Coyote
sn: Coyote
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
# Re-search for memberOf=cn=Mixer3 with filter and value nesting...
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Porky Pig,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Road Runner,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Road Runner
sn: Runner
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: cn=Wile E. Coyote,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Wile E. Coyote
sn: Coyote
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
# Re-search the entire database with memberof value nesting...
dn: cn=A-M,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Baby Herman,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Baby Herman
sn: Herman
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer2,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Bugs Bunny,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Bugs Bunny
sn: Bunny
memberOf: cn=Leporidae,ou=Groups,dc=example,dc=com
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Daffy Duck,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Daffy Duck
sn: Duck
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Desert Foes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Elmer Fudd,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Elmer Fudd
sn: Fudd
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Humans,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer2,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Endless Loop,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Endless Loop
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: dc=example,dc=com
objectClass: organization
objectClass: dcObject
o: Example, Inc.
dc: example
dn: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Foghorn Leghorn
sn: Leghorn
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups
dn: cn=Humans,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Humans
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
memberOf: cn=Mixer2,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Jessica Rabbit,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Jessica Rabbit
sn: Rabbit
memberOf: cn=Rabbits,ou=Groups,dc=example,dc=com
memberOf: cn=A-M,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
memberOf: cn=Leporidae,ou=Groups,dc=example,dc=com
dn: cn=Leporidae,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Rabbits,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
dn: cn=Looney Tunes,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Daffy Duck,ou=People,dc=example,dc=com
member: cn=Elmer Fudd,ou=People,dc=example,dc=com
member: cn=Bugs Bunny,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
dn: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Loop, Endless
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: cn=Mixer1,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer1
member: cn=Leporidae,ou=Groups,dc=example,dc=com
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
dn: cn=Mixer2,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer2
member: cn=Humans,ou=Groups,dc=example,dc=com
member: cn=Baby Herman,ou=People,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Mixer3,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer3
member: cn=Desert Foes,ou=Groups,dc=example,dc=com
member: cn=Porky Pig,ou=People,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Mixer4,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer4
member: cn=Mixer1,ou=Groups,dc=example,dc=com
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Foghorn Leghorn,ou=People,dc=example,dc=com
dn: cn=Mixer5,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Mixer5
member: cn=Mixer2,ou=Groups,dc=example,dc=com
member: cn=Mixer3,ou=Groups,dc=example,dc=com
member: cn=A-M,ou=Groups,dc=example,dc=com
dn: cn=N-Z,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: N-Z
member: cn=Porky Pig,ou=People,dc=example,dc=com
member: cn=Road Runner,ou=People,dc=example,dc=com
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Tweety Bird,ou=People,dc=example,dc=com
member: cn=Wile E. Coyote,ou=People,dc=example,dc=com
member: cn=Yosemite Sam,ou=People,dc=example,dc=com
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People
dn: cn=Porky Pig,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
dn: cn=Rabbits,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
cn: Rabbits
member: cn=Roger Rabbit,ou=People,dc=example,dc=com
member: cn=Jessica Rabbit,ou=People,dc=example,dc=com
memberOf: cn=Leporidae,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
dn: cn=Road Runner,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Road Runner
sn: Runner
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
dn: cn=Roger Rabbit,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Roger Rabbit
sn: Rabbit
memberOf: cn=Rabbits,ou=Groups,dc=example,dc=com
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Leporidae,ou=Groups,dc=example,dc=com
dn: cn=Tweety Bird,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Tweety Bird
sn: Bird
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Looney Tunes,ou=Groups,dc=example,dc=com
dn: cn=Wile E. Coyote,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Wile E. Coyote
sn: Coyote
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Desert Foes,ou=Groups,dc=example,dc=com
memberOf: cn=Loop\2C Endless,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer1,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer3,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com
memberOf: cn=Endless Loop,ou=Groups,dc=example,dc=com
dn: cn=Yosemite Sam,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
cn: Yosemite Sam
sn: Sam
memberOf: cn=N-Z,ou=Groups,dc=example,dc=com
memberOf: cn=Humans,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer2,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer4,ou=Groups,dc=example,dc=com
memberOf: cn=Mixer5,ou=Groups,dc=example,dc=com

View File

@ -42,6 +42,7 @@ sed -e "s/@BACKEND@/${BACKEND}/" \
-e "s/^#${AC_dynlist}#//" \
-e "s/^#${AC_homedir}#//" \
-e "s/^#${AC_memberof}#//" \
-e "s/^#${AC_nestgroup}#//" \
-e "s/^#${AC_pcache}#//" \
-e "s/^#${AC_ppolicy}#//" \
-e "s/^#${AC_refint}#//" \

View File

@ -53,6 +53,7 @@ DEREF=${AC_deref-derefno}
DYNLIST=${AC_dynlist-dynlistno}
HOMEDIR=${AC_homedir-homedirno}
MEMBEROF=${AC_memberof-memberofno}
NESTGROUP=${AC_nestgroup-nestgroupno}
OTP=${AC_otp-otpno}
PROXYCACHE=${AC_pcache-pcacheno}
PPOLICY=${AC_ppolicy-ppolicyno}
@ -462,6 +463,8 @@ DDSOUT=$DATADIR/dds.out
DEREFOUT=$DATADIR/deref.out
MEMBEROFOUT=$DATADIR/memberof.out
MEMBEROFREFINTOUT=$DATADIR/memberof-refint.out
NESTGROUPOUT1=$DATADIR/nestgroup.out.1
NESTGROUPOUT2=$DATADIR/nestgroup.out.2
SHTOOL="$TOPSRCDIR/build/shtool"
. $ABS_SRCDIR/scripts/functions.sh

662
tests/scripts/test089-nestgroup Executable file
View File

@ -0,0 +1,662 @@
#! /bin/sh
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2024 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
if test $NESTGROUP = nestgroupno; then
echo "Nestgroup overlay not available, test skipped"
exit 0
fi
if test $MEMBEROF = memberofno; then
echo "Memberof overlay not available, memberof testing disabled"
fi
mkdir -p $TESTDIR $DBDIR1 $TESTDIR/confdir
$SLAPPASSWD -g -n >$CONFIGPWF
echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
echo "Starting slapd on TCP/IP port $PORT1..."
. $CONFFILTER $BACKEND < $NAKEDCONF > $CONF1
$SLAPD -f $CONF1 -F $TESTDIR/confdir -h $URI1 -d $LVL > $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$PID"
sleep 1
for i in 0 1 2 3 4 5; do
$LDAPSEARCH -s base -b "$MONITOR" -H $URI1 \
'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 0 ; then
break
fi
echo "Waiting 5 seconds for slapd to start..."
sleep 5
done
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
cat /dev/null > $TESTOUT
if [ "$NESTGROUP" = nestgroupmod ]; then
echo "Inserting nestgroup overlay on provider..."
$LDAPADD -D cn=config -H $URI1 -y $CONFIGPWF <<EOF > $TESTOUT 2>&1
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulePath: ../servers/slapd/overlays
olcModuleLoad: nestgroup.la
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed for moduleLoad ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
fi
indexInclude="" mainInclude="" nullExclude=""
test $INDEXDB = indexdb || indexInclude="# "
test $MAINDB = maindb || mainInclude="# "
case $BACKEND in
null) nullExclude="# " ;;
esac
echo "Running ldapadd to build slapd config database..."
$LDAPADD -H $URI1 -D 'cn=config' -w `cat $CONFIGPWF` \
>> $TESTOUT 2>&1 <<EOF
dn: olcDatabase={1}$BACKEND,cn=config
objectClass: olcDatabaseConfig
${nullExclude}objectClass: olc${BACKEND}Config
olcDatabase: {1}$BACKEND
olcSuffix: $BASEDN
olcRootDN: cn=Manager,$BASEDN
olcRootPW:: c2VjcmV0
olcMonitoring: TRUE
${nullExclude}olcDbDirectory: $TESTDIR/db.1.a/
${indexInclude}olcDbIndex: objectClass eq
${indexInclude}olcDbIndex: cn pres,eq,sub
${indexInclude}olcDbIndex: uid pres,eq,sub
${indexInclude}olcDbIndex: sn pres,eq,sub
${indexInclude}olcDbIndex: member,memberOf eq
${mainInclude}olcDbMode: 384"
dn: olcOverlay={0}nestgroup,olcDatabase={1}$BACKEND,cn=config
objectClass: olcOverlayConfig
objectClass: olcNestGroupConfig
olcOverlay: {0}nestgroup
olcNestgroupMember: member
olcNestgroupMemberOf: memberOf
olcNestgroupBase: ou=Groups,$BASEDN
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Running ldapadd to build slapd database..."
$LDAPADD -H $URI1 \
-D "cn=Manager,$BASEDN" -w secret \
>> $TESTOUT 2>&1 << EOF
dn: $BASEDN
objectClass: organization
objectClass: dcObject
o: Example, Inc.
dc: example
dn: ou=People,$BASEDN
objectClass: organizationalUnit
ou: People
dn: ou=Groups,$BASEDN
objectClass: organizationalUnit
ou: Groups
dn: cn=Roger Rabbit,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Roger Rabbit
sn: Rabbit
dn: cn=Baby Herman,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Baby Herman
sn: Herman
dn: cn=Jessica Rabbit,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Jessica Rabbit
sn: Rabbit
dn: cn=Bugs Bunny,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Bugs Bunny
sn: Bunny
dn: cn=Daffy Duck,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Daffy Duck
sn: Duck
dn: cn=Elmer Fudd,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Elmer Fudd
sn: Fudd
dn: cn=Yosemite Sam,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Yosemite Sam
sn: Sam
dn: cn=Foghorn Leghorn,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Foghorn Leghorn
sn: Leghorn
dn: cn=Wile E. Coyote,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Wile E. Coyote
sn: Coyote
dn: cn=Road Runner,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Road Runner
sn: Runner
dn: cn=Tweety Bird,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Tweety Bird
sn: Bird
dn: cn=Porky Pig,ou=People,$BASEDN
objectClass: inetOrgPerson
cn: Porky Pig
sn: Pig
dn: cn=Rabbits,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Rabbits
member: cn=Roger Rabbit,ou=People,$BASEDN
member: cn=Jessica Rabbit,ou=People,$BASEDN
dn: cn=Leporidae,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Leporidae
member: cn=Bugs Bunny,ou=People,$BASEDN
member: cn=Rabbits,ou=Groups,$BASEDN
dn: cn=A-M,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: A-M
member: cn=Baby Herman,ou=People,$BASEDN
member: cn=Bugs Bunny,ou=People,$BASEDN
member: cn=Daffy Duck,ou=People,$BASEDN
member: cn=Elmer Fudd,ou=People,$BASEDN
member: cn=Foghorn Leghorn,ou=People,$BASEDN
member: cn=Jessica Rabbit,ou=People,$BASEDN
dn: cn=N-Z,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: N-Z
member: cn=Porky Pig,ou=People,$BASEDN
member: cn=Road Runner,ou=People,$BASEDN
member: cn=Roger Rabbit,ou=People,$BASEDN
member: cn=Tweety Bird,ou=People,$BASEDN
member: cn=Wile E. Coyote,ou=People,$BASEDN
member: cn=Yosemite Sam,ou=People,$BASEDN
dn: cn=Humans,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Humans
member: cn=Elmer Fudd,ou=People,$BASEDN
member: cn=Yosemite Sam,ou=People,$BASEDN
dn: cn=Looney Tunes,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Looney Tunes
member: cn=Porky Pig,ou=People,$BASEDN
member: cn=Daffy Duck,ou=People,$BASEDN
member: cn=Elmer Fudd,ou=People,$BASEDN
member: cn=Bugs Bunny,ou=People,$BASEDN
member: cn=Tweety Bird,ou=People,$BASEDN
dn: cn=Desert Foes,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Desert Foes
member: cn=Road Runner,ou=People,$BASEDN
member: cn=Wile E. Coyote,ou=People,$BASEDN
dn: cn=Mixer1,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Mixer1
member: cn=Leporidae,ou=Groups,$BASEDN
member: cn=Desert Foes,ou=Groups,$BASEDN
member: cn=Foghorn Leghorn,ou=People,$BASEDN
dn: cn=Mixer2,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Mixer2
member: cn=Humans,ou=Groups,$BASEDN
member: cn=Baby Herman,ou=People,$BASEDN
dn: cn=Mixer3,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Mixer3
member: cn=Desert Foes,ou=Groups,$BASEDN
member: cn=Porky Pig,ou=People,$BASEDN
dn: cn=Mixer4,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Mixer4
member: cn=Mixer1,ou=Groups,$BASEDN
member: cn=Mixer2,ou=Groups,$BASEDN
member: cn=Foghorn Leghorn,ou=People,$BASEDN
dn: cn=Mixer5,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Mixer5
member: cn=Mixer2,ou=Groups,$BASEDN
member: cn=Mixer3,ou=Groups,$BASEDN
member: cn=A-M,ou=Groups,$BASEDN
dn: cn=Endless Loop,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Endless Loop
member: cn=Road Runner,ou=People,$BASEDN
member: cn=Loop\, Endless,ou=Groups,$BASEDN
dn: cn=Loop\, Endless,ou=Groups,$BASEDN
objectClass: groupOfNames
cn: Loop, Endless
member: cn=Wile E. Coyote,ou=People,$BASEDN
member: cn=Endless Loop,ou=Groups,$BASEDN
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Search the entire database..."
echo "# Search the entire database..." > $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
'(objectClass=*)' '*' >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Search for member=cn=Bugs Bunny..."
echo "# Search for member=cn=Bugs Bunny..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
"(member=cn=Bugs Bunny,ou=People,$BASEDN)" '*' memberof >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Running ldapmodify to enable nested member filter..."
$LDAPMODIFY -H $URI1 -D 'cn=config' -w `cat $CONFIGPWF` \
>> $TESTOUT 2>&1 <<EOF
dn: olcOverlay={0}nestgroup,olcDatabase={1}$BACKEND,cn=config
changetype: modify
replace: olcNestgroupFlags
olcNestgroupFlags: member-filter
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Re-search for nested member=cn=Bugs Bunny..."
echo "# Re-search for nested member=cn=Bugs Bunny..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
"(member=cn=Bugs Bunny,ou=People,$BASEDN)" '*' memberof >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Running ldapmodify to enable nested member values..."
$LDAPMODIFY -H $URI1 -D 'cn=config' -w `cat $CONFIGPWF` \
>> $TESTOUT 2>&1 <<EOF
dn: olcOverlay={0}nestgroup,olcDatabase={1}$BACKEND,cn=config
changetype: modify
replace: olcNestgroupFlags
olcNestgroupFlags: member-values
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Search the expanded groups..."
echo "# Search the expanded groups..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "ou=Groups,$BASEDN" -H $URI1 \
'(objectClass=*)' '*' memberof >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
LDIF=$NESTGROUPOUT1
echo "Filtering ldapsearch results..."
$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
echo "Filtering original ldif used to create database..."
$LDIFFILTER < $LDIF > $LDIFFLT
echo "Comparing filter output..."
$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
if test $? != 0 ; then
echo "Comparison failed"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit 1
fi
echo ">>>>> Test succeeded (first half)"
if [ "$MEMBEROF" = memberofno ]; then
test $KILLSERVERS != no && kill -HUP $KILLPIDS
test $KILLSERVERS != no && wait
exit 0
fi
echo "Adding memberof overlay to database configuration..."
if [ "$MEMBEROF" = memberofmod ]; then
echo "Inserting memberof module on provider..."
$LDAPADD -D cn=config -H $URI1 -y $CONFIGPWF <<EOF > $TESTOUT 2>&1
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulePath: ../servers/slapd/overlays
olcModuleLoad: memberof.la
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed for moduleLoad ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
fi
$LDAPADD -H $URI1 -D 'cn=config' -w `cat $CONFIGPWF` \
>> $TESTOUT 2>&1 <<EOF
dn: olcOverlay={1}memberof,olcDatabase={1}$BACKEND,cn=config
objectClass: olcOverlayConfig
objectClass: olcMemberofConfig
olcOverlay: {1}memberof
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Recreating group entries to set memberof values..."
$LDAPMODIFY -H $URI1 \
-D "cn=Manager,$BASEDN" -w secret \
>> $TESTOUT 2>&1 <<EOF
dn: cn=Rabbits,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Roger Rabbit,ou=People,$BASEDN
member: cn=Jessica Rabbit,ou=People,$BASEDN
dn: cn=Leporidae,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Bugs Bunny,ou=People,$BASEDN
member: cn=Rabbits,ou=Groups,$BASEDN
dn: cn=A-M,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Baby Herman,ou=People,$BASEDN
member: cn=Bugs Bunny,ou=People,$BASEDN
member: cn=Daffy Duck,ou=People,$BASEDN
member: cn=Elmer Fudd,ou=People,$BASEDN
member: cn=Foghorn Leghorn,ou=People,$BASEDN
member: cn=Jessica Rabbit,ou=People,$BASEDN
dn: cn=N-Z,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Porky Pig,ou=People,$BASEDN
member: cn=Road Runner,ou=People,$BASEDN
member: cn=Roger Rabbit,ou=People,$BASEDN
member: cn=Tweety Bird,ou=People,$BASEDN
member: cn=Wile E. Coyote,ou=People,$BASEDN
member: cn=Yosemite Sam,ou=People,$BASEDN
dn: cn=Humans,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Elmer Fudd,ou=People,$BASEDN
member: cn=Yosemite Sam,ou=People,$BASEDN
dn: cn=Looney Tunes,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Porky Pig,ou=People,$BASEDN
member: cn=Daffy Duck,ou=People,$BASEDN
member: cn=Elmer Fudd,ou=People,$BASEDN
member: cn=Bugs Bunny,ou=People,$BASEDN
member: cn=Tweety Bird,ou=People,$BASEDN
dn: cn=Desert Foes,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Road Runner,ou=People,$BASEDN
member: cn=Wile E. Coyote,ou=People,$BASEDN
dn: cn=Mixer1,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Leporidae,ou=Groups,$BASEDN
member: cn=Desert Foes,ou=Groups,$BASEDN
member: cn=Foghorn Leghorn,ou=People,$BASEDN
dn: cn=Mixer2,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Humans,ou=Groups,$BASEDN
member: cn=Baby Herman,ou=People,$BASEDN
dn: cn=Mixer3,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Desert Foes,ou=Groups,$BASEDN
member: cn=Porky Pig,ou=People,$BASEDN
dn: cn=Mixer4,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Mixer1,ou=Groups,$BASEDN
member: cn=Mixer2,ou=Groups,$BASEDN
member: cn=Foghorn Leghorn,ou=People,$BASEDN
dn: cn=Mixer5,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Mixer2,ou=Groups,$BASEDN
member: cn=Mixer3,ou=Groups,$BASEDN
member: cn=A-M,ou=Groups,$BASEDN
dn: cn=Endless Loop,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Road Runner,ou=People,$BASEDN
member: cn=Loop\, Endless,ou=Groups,$BASEDN
dn: cn=Loop\, Endless,ou=Groups,$BASEDN
changetype: modify
replace: member
member: cn=Wile E. Coyote,ou=People,$BASEDN
member: cn=Endless Loop,ou=Groups,$BASEDN
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Moving previous results to $SEARCHOUT.0"
mv $SEARCHOUT $SEARCHOUT.0
echo "Re-search the entire database..."
echo "# Re-search the entire database after adding memberof configuration..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
'(objectClass=*)' '*' memberOf >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Search for memberOf=cn=Mixer3..."
echo "# Search for memberOf=cn=Mixer3..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
"(memberOf=cn=Mixer3,ou=Groups,$BASEDN)" '*' memberof >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Running ldapmodify to enable nested memberOf filter..."
$LDAPMODIFY -H $URI1 -D 'cn=config' -w `cat $CONFIGPWF` \
>> $TESTOUT 2>&1 <<EOF
dn: olcOverlay={0}nestgroup,olcDatabase={1}$BACKEND,cn=config
changetype: modify
replace: olcNestgroupFlags
olcNestgroupFlags: memberof-filter
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Re-search for memberOf=cn=Mixer3 with filter nesting..."
echo "# Re-search for memberOf=cn=Mixer3 with filter nesting..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
"(memberOf=cn=Mixer3,ou=Groups,$BASEDN)" '*' memberof >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Running ldapmodify to also enable nested memberOf values..."
$LDAPMODIFY -H $URI1 -D 'cn=config' -w `cat $CONFIGPWF` \
>> $TESTOUT 2>&1 <<EOF
dn: olcOverlay={0}nestgroup,olcDatabase={1}$BACKEND,cn=config
changetype: modify
add: olcNestgroupFlags
olcNestgroupFlags: memberof-values
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Re-search for memberOf=cn=Mixer3 with filter and value nesting..."
echo "# Re-search for memberOf=cn=Mixer3 with filter and value nesting..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
"(memberOf=cn=Mixer3,ou=Groups,$BASEDN)" '*' memberof >> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Re-search the entire database with memberof value nesting..."
echo "# Re-search the entire database with memberof value nesting..." >> $SEARCHOUT
$LDAPSEARCH -S "" -b "$BASEDN" -H $URI1 \
'(objectClass=*)' '*' memberOf >> $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=$NESTGROUPOUT2
echo "Filtering ldapsearch results..."
$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
echo "Filtering original ldif used to create database..."
$LDIFFILTER < $LDIF > $LDIFFLT
echo "Comparing filter output..."
$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
if test $? != 0 ; then
echo "Comparison failed"
exit 1
fi
echo ">>>>> Test succeeded"
test $KILLSERVERS != no && wait
exit 0