[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: dynamic groups
Hello,
I'm attaching the "Really dynamic list" overlay, on which I have been
working for the past 2 weeks. This is the Technology Preview version, so
I need your input on the implementation. Also feel free to criticize, or
to point out the flaws in my understanding of OpenLDAP, or the
implementation of this overlay.
I have tested it, and it works without problems (at least on my setup).
This overlay works by updating the dynamic list entry's member attribute
(which is not modifiable by the user) on an add/delete/modify/modrdn
operation, adding or deleting the updated entry's DN to/from the dynamic
list when the entry matches the any of the memberURL filters of the
dynamic list.
I have modified the dyngroup schema slightly, adding the 'member'
attribute to the MAY clause. This is needed to store the 'materialized'
member DN's in the dynamic list entry in the database.
The config is similar to the dynlist overlay, but with mandatory member
attribute:
rdynlist-attrset <group-oc> <URL-ad> <member-ad>
* rdynlist.patch is the patch for the schema and the
configure/makefiles.
--
MichaÅ SzulczyÅski
Praktykant
Altkom Akademia S.A. http://www.altkom.pl
Warszawa, ul. ChÅodna 51
SÄd Rejonowy dla m.st. Warszawy w Warszawie, XII WydziaÅ Gospodarczy Krajowego Rejestru SÄdowego,
KRS: 0000120139, NIP 118-00-08-391, KapitaÅ zakÅadowy: 1000 000 PLN. Adres rejestrowy Firmy - ul. Stawki 2, 00-193 Warszawa.
Niniejsza wiadomoÅÄ zawiera informacje zastrzeÅone i stanowiÄce tajemnicÄ przedsiÄbiorstwa firmy Altkom Akademia S.A.
Ujawnianie tych informacji osobom trzecim lub nieuprawnione wykorzystanie ich do wÅasnych celÃw jest zabronione.
JeÅeli otrzymaliÅcie PaÅstwo niniejszÄ wiadomoÅÄ omyÅkowo, prosimy o niezwÅoczne skontaktowanie siÄ z nadawcÄ oraz usuniÄcie wszelkich kopii niniejszej wiadomoÅci.
This message contains proprietary information and trade secrets of Altkom Akademia S.A. company.
Unauthorized use or disclosure of this information to any third party is prohibited.
If you received this message by mistake, please contact the sender immediately and delete all copies of this message.
Index: configure.in
===================================================================
RCS file: /repo/OpenLDAP/pkg/ldap/configure.in,v
retrieving revision 1.660
diff -u -r1.660 configure.in
--- configure.in 7 Sep 2007 10:02:43 -0000 1.660
+++ configure.in 13 Sep 2007 09:28:13 -0000
@@ -334,6 +334,7 @@
dds \
dyngroup \
dynlist \
+ rdynlist \
memberof \
ppolicy \
proxycache \
@@ -363,6 +364,8 @@
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(dynlist,[ --enable-dynlist Dynamic List overlay],
no, [no yes mod], ol_enable_overlays)
+OL_ARG_ENABLE(rdynlist,[ --enable-rdynlist Really Dynamic List overlay],
+ no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(memberof,[ --enable-memberof Reverse Group Membership overlay],
no, [no yes mod], ol_enable_overlays)
OL_ARG_ENABLE(ppolicy,[ --enable-ppolicy Password Policy overlay],
@@ -533,6 +536,7 @@
BUILD_DENYOP=no
BUILD_DYNGROUP=no
BUILD_DYNLIST=no
+BUILD_RDYNLIST=no
BUILD_LASTMOD=no
BUILD_PPOLICY=no
BUILD_PROXYCACHE=no
@@ -2737,6 +2741,18 @@
AC_DEFINE_UNQUOTED(SLAPD_OVER_DYNLIST,$MFLAG,[define for Dynamic List overlay])
fi
+if test "$ol_enable_rdynlist" != no ; then
+ BUILD_RDYNLIST=$ol_enable_rdynlist
+ if test "$ol_enable_rdynlist" = mod ; then
+ MFLAG=SLAPD_MOD_DYNAMIC
+ SLAPD_DYNAMIC_OVERLAYS="$SLAPD_DYNAMIC_OVERLAYS rdynlist.la"
+ else
+ MFLAG=SLAPD_MOD_STATIC
+ SLAPD_STATIC_OVERLAYS="$SLAPD_STATIC_OVERLAYS rdynlist.o"
+ fi
+ AC_DEFINE_UNQUOTED(SLAPD_OVER_RDYNLIST,$MFLAG,[define for Really Dynamic List overlay])
+fi
+
if test "$ol_enable_memberof" != no ; then
BUILD_MEMBEROF=$ol_enable_memberof
if test "$ol_enable_memberof" = mod ; then
@@ -2930,6 +2946,7 @@
AC_SUBST(BUILD_DENYOP)
AC_SUBST(BUILD_DYNGROUP)
AC_SUBST(BUILD_DYNLIST)
+ AC_SUBST(BUILD_RDYNLIST)
AC_SUBST(BUILD_LASTMOD)
AC_SUBST(BUILD_PPOLICY)
AC_SUBST(BUILD_PROXYCACHE)
Index: include/portable.hin
===================================================================
RCS file: /repo/OpenLDAP/pkg/ldap/include/portable.hin,v
retrieving revision 1.40
diff -u -r1.40 portable.hin
--- include/portable.hin 9 Sep 2007 12:23:36 -0000 1.40
+++ include/portable.hin 13 Sep 2007 09:28:13 -0000
@@ -966,6 +966,9 @@
/* define for Dynamic List overlay */
#undef SLAPD_OVER_DYNLIST
+/* define for Really Dynamic List overlay */
+#undef SLAPD_OVER_RDYNLIST
+
/* define for Reverse Group Membership overlay */
#undef SLAPD_OVER_MEMBEROF
Index: servers/slapd/bconfig.c
===================================================================
RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/bconfig.c,v
retrieving revision 1.303
diff -u -r1.303 bconfig.c
--- servers/slapd/bconfig.c 2 Sep 2007 22:40:52 -0000 1.303
+++ servers/slapd/bconfig.c 13 Sep 2007 09:28:14 -0000
@@ -250,6 +250,7 @@
* OLcfgOv{Oc|At}:17 -> dyngroup
* OLcfgOv{Oc|At}:18 -> memberof
* OLcfgOv{Oc|At}:19 -> collect
+ * OLcfgOv{Oc|At}:20 -> rdynlist
*/
/* alphabetical ordering */
Index: servers/slapd/overlays/Makefile.in
===================================================================
RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/Makefile.in,v
retrieving revision 1.47
diff -u -r1.47 Makefile.in
--- servers/slapd/overlays/Makefile.in 24 Aug 2007 00:46:58 -0000 1.47
+++ servers/slapd/overlays/Makefile.in 13 Sep 2007 09:28:14 -0000
@@ -20,6 +20,7 @@
dds.c \
dyngroup.c \
dynlist.c \
+ rdynlist.c \
memberof.c \
pcache.c \
ppolicy.c \
@@ -77,6 +78,9 @@
dynlist.la : dynlist.lo
$(LTLINK_MOD) -module -o $@ dynlist.lo version.lo $(LINK_LIBS)
+rdynlist.la : rdynlist.lo
+ $(LTLINK_MOD) -module -o $@ rdynlist.lo version.lo $(LINK_LIBS)
+
memberof.la : memberof.lo
$(LTLINK_MOD) -module -o $@ memberof.lo version.lo $(LINK_LIBS)
Index: servers/slapd/schema/dyngroup.schema
===================================================================
RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/schema/dyngroup.schema,v
retrieving revision 1.13
diff -u -r1.13 dyngroup.schema
--- servers/slapd/schema/dyngroup.schema 25 Aug 2007 07:37:59 -0000 1.13
+++ servers/slapd/schema/dyngroup.schema 13 Sep 2007 09:28:14 -0000
@@ -72,7 +72,7 @@
SUP top STRUCTURAL
MUST cn
MAY ( memberURL $ businessCategory $ description $ o $ ou $
- owner $ seeAlso ) )
+ owner $ seeAlso $ member ) )
# The Haripriya dyngroup schema still needs a lot of work.
# We're just adding support for the dgIdentity attribute for now...
/* rdynlist.c - really dynamic list overlay */
/* $OpenLDAP: $ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2007 MichaÅ SzulczyÅski.
* 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 MichaÅ SzulczyÅski
* for Altkom Akademia S.A., for inclusion in OpenLDAP Software.
*/
#include "portable.h"
#ifdef SLAPD_OVER_RDYNLIST
#include <stdio.h>
#include <ac/string.h>
#include "slap.h"
#include "config.h"
#include "lutil.h"
typedef struct rdynlist_filter_t {
struct berval rdlf_dn;
struct berval rdlf_ndn;
struct berval rdlf_filterstr;
Filter *rdlf_filter;
int rdlf_scope;
struct rdynlist_filter_t *rdlf_next;
} rdynlist_filter_t;
typedef struct rdynlist_def_t {
ObjectClass *rdld_oc;
AttributeDescription *rdld_member_url_ad;
AttributeDescription *rdld_member_ad;
struct rdynlist_def_t *rdld_next;
} rdynlist_def_t;
typedef struct rdynlist_entry_t {
BerValue rdle_dn;
BerValue rdle_ndn;
rdynlist_filter_t *rdle_filter;
rdynlist_def_t *rdle_def; /* Parent definition */
ldap_pvt_thread_mutex_t rdle_mutex;
struct rdynlist_entry_t *rdle_next;
} rdynlist_entry_t;
typedef struct rdynlist_info_t {
rdynlist_def_t *rdli_def;
rdynlist_entry_t *rdli_entry;
ldap_pvt_thread_mutex_t rdli_mutex;
} rdynlist_info_t;
/* Search callback for adding groups initially. */
typedef struct rdynlist_sc_t {
rdynlist_info_t *rdls_info;
rdynlist_def_t *rdls_def;
} rdynlist_sc_t;
/* Used for adding members, found when searching, to group. */
typedef struct rdynlist_ga_t {
rdynlist_entry_t *rdlg_group;
Entry *rdlg_entry;
} rdynlist_ga_t;
static int
rdynlist_add_member_to_group( Operation *op, BerValue *dn, BerValue *ndn, rdynlist_entry_t *rdle )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
Modifications modlist;
SlapReply sreply = {REP_RESULT};
BerValue vals[ 2 ], nvals[ 2 ];
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
Operation o = *op;
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_add_member_to_group adding <%s> to <%s>\n",
dn->bv_val, rdle->rdle_dn.bv_val, 0);
assert( dn != NULL );
assert( ndn != NULL );
vals[ 0 ] = *dn;
BER_BVZERO( &vals[ 1 ] );
nvals[ 0 ] = *ndn;
BER_BVZERO( &nvals[ 1 ] );
modlist.sml_op = LDAP_MOD_ADD;
modlist.sml_desc = rdle->rdle_def->rdld_member_ad;
modlist.sml_type = rdle->rdle_def->rdld_member_ad->ad_cname;
modlist.sml_values = vals;
modlist.sml_nvalues = nvals;
modlist.sml_flags = SLAP_MOD_INTERNAL;
modlist.sml_next = NULL;
o.o_tag = LDAP_REQ_MODIFY;
o.o_callback = &cb;
o.orm_modlist = &modlist;
o.o_req_dn = rdle->rdle_dn;
o.o_req_ndn = rdle->rdle_ndn;
o.o_permissive_modify = 1;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
o.o_relax = SLAP_CONTROL_CRITICAL;
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &sreply );
o.o_bd->bd_info = (BackendInfo *)on;
return sreply.sr_err;
}
static int
rdynlist_delete_member_from_group( Operation *op, BerValue *dn, BerValue *ndn, rdynlist_entry_t *rdle )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
Modifications modlist;
SlapReply sreply = {REP_RESULT};
BerValue vals[ 2 ], nvals[ 2 ];
slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
Operation o = *op;
if ( dn == NULL || ndn == NULL ) {
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_delete_member_from_group removing all members from <%s>\n",
rdle->rdle_dn.bv_val, 0 ,0);
modlist.sml_values = NULL;
modlist.sml_nvalues = NULL;
} else {
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_delete_member_from_group removing <%s> from <%s>\n",
dn->bv_val, rdle->rdle_dn.bv_val, 0);
vals[ 0 ] = *dn;
BER_BVZERO( &vals[ 1 ] );
nvals[ 0 ] = *ndn;
BER_BVZERO( &nvals[ 1 ] );
modlist.sml_values = vals;
modlist.sml_nvalues = nvals;
}
modlist.sml_op = LDAP_MOD_DELETE;
modlist.sml_desc = rdle->rdle_def->rdld_member_ad;
modlist.sml_type = rdle->rdle_def->rdld_member_ad->ad_cname;
modlist.sml_flags = SLAP_MOD_INTERNAL;
modlist.sml_next = NULL;
o.o_callback = &cb;
o.o_tag = LDAP_REQ_MODIFY;
o.orm_modlist = &modlist;
o.o_req_dn = rdle->rdle_dn;
o.o_req_ndn = rdle->rdle_ndn;
o.o_relax = SLAP_CONTROL_CRITICAL;
o.o_managedsait = SLAP_CONTROL_CRITICAL;
o.o_permissive_modify = 1;
o.o_bd->bd_info = (BackendInfo *)on->on_info;
(void)op->o_bd->be_modify( &o, &sreply );
o.o_bd->bd_info = (BackendInfo *)on;
return sreply.sr_err;
}
static int
rdynlist_member_search_cb( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
assert( op->o_tag == LDAP_REQ_SEARCH );
if ( rs->sr_type == REP_SEARCH ) {
rdynlist_ga_t *rdlg = (rdynlist_ga_t *)op->o_callback->sc_private;
rdynlist_entry_t *rdle = rdlg->rdlg_group;
Modification mod;
const char *text = NULL;
char textbuf[1024];
struct berval vals[ 2 ], nvals[ 2 ];
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_member_search_cb <%s>\n",
rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
vals[ 0 ] = rs->sr_entry->e_name;
BER_BVZERO( &vals[ 1 ] );
nvals[ 0 ] = rs->sr_entry->e_nname;
BER_BVZERO( &nvals[ 1 ] );
mod.sm_op = LDAP_MOD_ADD;
mod.sm_desc = rdle->rdle_def->rdld_member_ad;
mod.sm_type = rdle->rdle_def->rdld_member_ad->ad_cname;
mod.sm_values = vals;
mod.sm_nvalues = nvals;
modify_add_values( rdlg->rdlg_entry, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
}
if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
entry_free( rs->sr_entry );
rs->sr_entry = NULL;
rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
}
return 0;
}
/* We must supply a rw entry. */
static int
rdynlist_add_members_from_filter( Operation *op, Entry *e, rdynlist_entry_t *rdle, rdynlist_filter_t *rdlf)
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
Operation o = *op;
SlapReply rs = { REP_SEARCH };
slap_callback cb = { 0 };
rdynlist_ga_t rdlg;
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_add_members_from_filter <%s>\n",
rdle->rdle_dn.bv_val, 0, 0);
o.ors_attrsonly = 0;
o.o_tag = LDAP_REQ_SEARCH;
o.o_req_dn = rdlf->rdlf_dn;
o.o_req_ndn = rdlf->rdlf_ndn;
o.ors_filterstr = rdlf->rdlf_filterstr;
o.ors_filter = rdlf->rdlf_filter;
o.ors_scope = rdlf->rdlf_scope;
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 = slap_anlist_no_attrs;
rdlg.rdlg_group = rdle;
rdlg.rdlg_entry = e;
cb.sc_private = &rdlg;
cb.sc_response = rdynlist_member_search_cb;
cb.sc_cleanup = NULL;
cb.sc_next = NULL;
o.o_callback = &cb;
o.o_bd->bd_info = (BackendInfo *)on->on_info;
op->o_bd->be_search( &o, &rs );
o.o_bd->bd_info = (BackendInfo *)on;
return 0;
}
static int
rdynlist_add_group( Operation *op, rdynlist_info_t *rdli, rdynlist_def_t *rdld, Entry *e, int scan)
{
rdynlist_entry_t **rdlep = &rdli->rdli_entry;
rdynlist_filter_t *rdlf, *rdlf_prev = NULL;
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
LDAPURLDesc *lud = NULL;
Attribute *a;
BerValue *bv, dn;
int rc = 0, match = 1;
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_add_group <%s>\n",
e->e_name.bv_val, 0, 0);
if ( rdli->rdli_entry != NULL ) {
for ( ; *rdlep ; rdlep = &(*rdlep)->rdle_next ) {
dnMatch( &match, 0, NULL, NULL, &e->e_nname, &(*rdlep)->rdle_ndn );
if ( match == 0 ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_add_group: group already exists: <%s>\n", e->e_name.bv_val,0,0);
return 1;
}
/* goto last */;
}
}
*rdlep = (rdynlist_entry_t *)ch_calloc( 1, sizeof( rdynlist_entry_t ) );
/* TODO check if alloc was successful. */
ldap_pvt_thread_mutex_init( &(*rdlep)->rdle_mutex );
(*rdlep)->rdle_def = rdld;
ber_dupbv( &(*rdlep)->rdle_dn, &e->e_name );
ber_dupbv( &(*rdlep)->rdle_ndn, &e->e_nname );
a = attrs_find( e->e_attrs, rdld->rdld_member_url_ad );
if( a == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_add_group: group has no memberURL\n", 0,0,0);
} else {
for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
rdlf = (rdynlist_filter_t*)ch_calloc( 1, sizeof( rdynlist_filter_t ) );
if ( ldap_url_parse( bv->bv_val, &lud ) != LDAP_URL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_add_group: cannot parse url <%s>\n", bv->bv_val,0,0);
/* FIXME: error? */
continue;
}
rdlf->rdlf_scope = lud->lud_scope;
if ( lud->lud_filter != NULL ) {
ber_str2bv( lud->lud_filter, 0, 0, &rdlf->rdlf_filterstr);
rdlf->rdlf_filter = str2filter( lud->lud_filter );
}
if ( lud->lud_dn == NULL ) {
BER_BVSTR( &dn, "" );
} else {
ber_str2bv( lud->lud_dn, 0, 0, &dn );
}
rc = dnPrettyNormal( NULL, &dn, &rdlf->rdlf_dn, &rdlf->rdlf_ndn, NULL );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_add_group: cannot normalize DN <%s>\n", dn.bv_val,0,0);
/* FIXME: error? */
goto cleanup;
}
if( (*rdlep)->rdle_filter == NULL ) {
(*rdlep)->rdle_filter = rdlf;
}
if( rdlf_prev != NULL ) {
rdlf_prev->rdlf_next = rdlf;
}
rdlf_prev = rdlf;
if ( scan == 1 ){
rdynlist_add_members_from_filter( op, e, (*rdlep), rdlf );
}
Debug( LDAP_DEBUG_TRACE, "rdynlist_add_group: added memberURL DN <%s> with filter <%s>\n", rdlf->rdlf_ndn.bv_val, rdlf->rdlf_filterstr.bv_val, 0);
continue;
cleanup:;
ch_free( rdlf );
ldap_free_urldesc( lud );
}
}
return rc;
}
static int
rdynlist_group_add_cb( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
assert( op->o_tag == LDAP_REQ_SEARCH );
if ( rs->sr_type == REP_SEARCH ) {
rdynlist_sc_t *rdls = (rdynlist_sc_t *)op->o_callback->sc_private;
Debug(LDAP_DEBUG_TRACE, "==> rdynlist_group_add_cb <%s>\n",
rs->sr_entry ? rs->sr_entry->e_name.bv_val : "UNKNOWN_DN", 0, 0);
rdynlist_add_group( op, rdls->rdls_info, rdls->rdls_def, rs->sr_entry, 0);
}
if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
entry_free( rs->sr_entry );
rs->sr_entry = NULL;
rs->sr_flags ^= REP_ENTRY_MUSTBEFREED;
}
return 0;
}
static int
rdynlist_add_entry( Operation *op, SlapReply *rs)
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
rdynlist_info_t *rdli = (rdynlist_info_t *)on->on_bi.bi_private;
rdynlist_def_t *rdld = rdli->rdli_def;
rdynlist_entry_t *rdle = rdli->rdli_entry;
rdynlist_filter_t *rdlf;
Attribute *a;
int rc = 0;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_add_entry <%s>\n",
op->ora_e->e_name.bv_val, 0, 0);
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
for ( ; rdld ; rdld = rdld->rdld_next ) {
if ( is_entry_objectclass_or_sub( op->ora_e, rdld->rdld_oc ) ) {
Modification mod;
const char *text = NULL;
char textbuf[1024];
mod.sm_op = LDAP_MOD_DELETE;
mod.sm_desc = rdld->rdld_member_ad;
mod.sm_type = rdld->rdld_member_ad->ad_cname;
mod.sm_values = NULL;
mod.sm_nvalues = NULL;
/* We don't want any member attributes added by the user. */
modify_delete_values( op->ora_e, &mod, /* permissive */ 1, &text, textbuf, sizeof( textbuf ) );
rdynlist_add_group( op, rdli, rdld, op->ora_e, 1 );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
}
for ( ; rdle ; rdle = rdle->rdle_next ) {
ldap_pvt_thread_mutex_lock( &rdle->rdle_mutex );
for ( rdlf = rdle->rdle_filter; rdlf ; rdlf = rdlf->rdlf_next ) {
if ( dnIsSuffix( &op->o_req_ndn, &rdlf->rdlf_ndn ) ) {
rc = test_filter( op, op->ora_e, rdlf->rdlf_filter );
if ( rc == LDAP_COMPARE_TRUE ) {
rdynlist_add_member_to_group( op, &op->ora_e->e_name, &op->ora_e->e_nname, rdle );
break;
}
}
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
static int
rdynlist_delete_group( rdynlist_info_t *rdli, rdynlist_entry_t *e )
{
rdynlist_entry_t *rdle = rdli->rdli_entry,
*rdle_prev = NULL,
*rdle_next;
int rc = 1;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_delete_group <%s>\n",
rdle->rdle_dn.bv_val, 0, 0);
for ( rdle_next = rdle ; rdle_next ; rdle_prev = rdle, rdle = rdle_next ) {
rdle_next = rdle->rdle_next;
if ( rdle == e ) {
rdynlist_filter_t *rdlf = rdle->rdle_filter,
*rdlf_next;
if ( rdle_prev != NULL ) {
rdle_prev->rdle_next = rdle_next;
}
ch_free( rdle->rdle_dn.bv_val );
ch_free( rdle->rdle_ndn.bv_val );
for( rdlf_next = rdlf ; rdlf_next ; rdlf = rdlf_next ){
rdlf_next = rdlf->rdlf_next;
filter_free( rdlf->rdlf_filter );
ch_free( rdlf->rdlf_filterstr.bv_val );
ch_free( rdlf->rdlf_dn.bv_val );
ch_free( rdlf->rdlf_ndn.bv_val );
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
ldap_pvt_thread_mutex_destroy( &rdle->rdle_mutex );
ch_free( rdle );
rc = 0;
return rc;
}
}
Debug( LDAP_DEBUG_TRACE, "rdynlist_delete_group: group <%s> not found, should not happen\n", rdle->rdle_dn.bv_val, 0, 0);
return rc;
}
static int
rdynlist_delete_entry( Operation *op, SlapReply *rs)
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
rdynlist_info_t *rdli = (rdynlist_info_t *)on->on_bi.bi_private;
rdynlist_def_t *rdld = rdli->rdli_def;
rdynlist_entry_t *rdle = rdli->rdli_entry,
*rdle_prev, *rdle_next;
rdynlist_filter_t *rdlf;
Entry *e;
int matched_group = 0, rc = 0;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_delete_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
LDAP_SUCCESS || e == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_delete_entry: cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
for ( rdle_next = rdle ; rdle_next ; rdle_prev = rdle, rdle = rdle_next ) {
ldap_pvt_thread_mutex_lock( &rdle->rdle_mutex );
rdle_next = rdle->rdle_next;
if ( is_entry_objectclass_or_sub( e, rdle->rdle_def->rdld_oc ) ) {
int match = 1;
matched_group = 1;
dnMatch( &match, 0, NULL, NULL, &e->e_nname, &rdle->rdle_ndn );
if ( match == 0 ) {
rdynlist_filter_t *rdlf = rdle->rdle_filter,
*rdlf_next;
rdynlist_delete_group( rdli, rdle );
break;
}
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
}
if ( matched_group == 1 ) {
overlay_entry_release_ov( op, e, 0, on );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
for ( rdle = rdli->rdli_entry ; rdle ; rdle = rdle->rdle_next ) {
ldap_pvt_thread_mutex_lock( &rdle->rdle_mutex );
for ( rdlf = rdle->rdle_filter; rdlf ; rdlf = rdlf->rdlf_next ) {
if ( dnIsSuffix( &op->o_req_ndn, &rdlf->rdlf_ndn ) ) {
rc = test_filter( op, e, rdlf->rdlf_filter );
if ( rc == LDAP_COMPARE_TRUE ) {
rdynlist_delete_member_from_group( op, &e->e_name, &e->e_nname, rdle );
break;
}
}
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
}
overlay_entry_release_ov( op, e, 0, on );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
static int
rdynlist_response( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
rdynlist_info_t *rdli = (rdynlist_info_t *)on->on_bi.bi_private;
rdynlist_def_t *rdld = rdli->rdli_def;
rdynlist_entry_t *rdle = rdli->rdli_entry;
rdynlist_filter_t *rdlf;
BerValue new_dn, new_ndn, pdn;
Entry *e, *group;
Attribute *a;
int is_olddn, is_newdn, dn_equal;
if ( op->o_tag == LDAP_REQ_MODRDN ) {
if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op )) {
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_response MODRDN from <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
if ( op->oq_modrdn.rs_newSup ) {
pdn = *op->oq_modrdn.rs_newSup;
} else {
dnParent( &op->o_req_dn, &pdn );
}
build_new_dn( &new_dn, &pdn, &op->orr_newrdn, NULL );
if ( op->oq_modrdn.rs_nnewSup ) {
pdn = *op->oq_modrdn.rs_nnewSup;
} else {
dnParent( &op->o_req_ndn, &pdn );
}
build_new_dn( &new_ndn, &pdn, &op->orr_nnewrdn, NULL );
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODRDN to <%s>\n", new_dn.bv_val, 0, 0);
dnMatch( &dn_equal, 0, NULL, NULL, &op->o_req_ndn, &new_ndn );
if ( overlay_entry_get_ov( op, &new_ndn, NULL, NULL, 0, &e, on ) !=
LDAP_SUCCESS || e == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODRDN cannot get entry for <%s>\n", new_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
overlay_entry_release_ov( op, e, 0, on );
if ( a == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODRDN entry <%s> has no objectClass\n", new_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
for ( ; rdld; rdld = rdld->rdld_next ) {
if ( value_find_ex( slap_schema.si_ad_objectClass,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a->a_nvals, &rdld->rdld_oc->soc_cname,
op->o_tmpmemctx ) == 0 )
{
for ( rdle = rdli->rdli_entry ; rdle ; rdle = rdle->rdle_next ) {
int match = 1;
dnMatch( &match, 0, NULL, NULL, &rdle->rdle_ndn, &op->o_req_ndn );
if ( match == 0 ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODRDN updating group's DN to <%s>\n", new_dn.bv_val, 0, 0);
ber_dupbv( &rdle->rdle_dn, &new_dn );
ber_dupbv( &rdle->rdle_ndn, &new_ndn );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
}
}
}
for ( rdle = rdli->rdli_entry ; rdle ; rdle = rdle->rdle_next ) {
is_olddn = 0;
is_newdn = 0;
ldap_pvt_thread_mutex_lock( &rdle->rdle_mutex );
if ( overlay_entry_get_ov( op, &rdle->rdle_ndn, NULL, NULL, 0, &group, on ) !=
LDAP_SUCCESS || group == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODRDN cannot get group entry <%s>\n", rdle->rdle_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
a = attrs_find( group->e_attrs, rdle->rdle_def->rdld_member_ad );
overlay_entry_release_ov( op, group, 0, on );
if ( a != NULL ) {
if ( value_find_ex( rdle->rdle_def->rdld_member_ad,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
{
is_olddn = 1;
}
}
for ( rdlf = rdle->rdle_filter ; rdlf ; rdlf = rdlf->rdlf_next ) {
if ( dnIsSuffix( &new_ndn, &rdlf->rdlf_ndn ) ) {
is_newdn = 1;
break;
}
}
if ( is_olddn == 1 && is_newdn == 0 ) {
rdynlist_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, rdle );
} else
if ( is_olddn == 0 && is_newdn == 1 ) {
for ( rdlf = rdle->rdle_filter; rdlf; rdlf = rdlf->rdlf_next ) {
if ( test_filter( op, e, rdlf->rdlf_filter ) == LDAP_COMPARE_TRUE ) {
rdynlist_add_member_to_group( op, &new_dn, &new_ndn, rdle );
break;
}
}
} else
if ( is_olddn == 1 && is_newdn == 1 && dn_equal != 0 ) {
rdynlist_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, rdle );
rdynlist_add_member_to_group( op, &new_dn, &new_ndn, rdle );
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
}
ch_free( new_dn.bv_val );
ch_free( new_ndn.bv_val );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
}
}
if ( op->o_tag == LDAP_REQ_MODIFY ) {
if ( rs->sr_type == REP_RESULT && rs->sr_err == LDAP_SUCCESS && !get_manageDSAit( op ) ) {
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_response MODIFY <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
LDAP_SUCCESS || e == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODIFY cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
if ( a == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODIFY entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
overlay_entry_release_ov( op, e, 0, on );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
for ( ; rdld; rdld = rdld->rdld_next ) {
if ( value_find_ex( slap_schema.si_ad_objectClass,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a->a_nvals, &rdld->rdld_oc->soc_cname,
op->o_tmpmemctx ) == 0 )
{
Modifications *m;
int match = 1;
m = op->orm_modlist;
for ( ; rdle ; rdle = rdle->rdle_next ) {
ldap_pvt_thread_mutex_lock( &rdle->rdle_mutex );
dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &rdle->rdle_ndn );
if ( match == 0 ) {
for ( ; m ; m = m->sml_next ) {
if ( m->sml_desc == rdle->rdle_def->rdld_member_url_ad ) {
rdynlist_def_t *group_rdld = rdle->rdle_def;
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODIFY changing memberURL for group <%s>\n",
op->o_req_dn.bv_val, 0, 0);
overlay_entry_release_ov( op, e, 0, on );
rdynlist_delete_member_from_group( op, NULL, NULL, rdle );
rdynlist_delete_group( rdli, rdle );
if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 1, &e, on ) !=
LDAP_SUCCESS || e == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODIFY cannot get entry for <%s>\n",
op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
rdynlist_add_group( op, rdli, group_rdld, e, 1);
overlay_entry_release_ov( op, e, 1, on );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
break;
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
}
overlay_entry_release_ov( op, e, 0, on );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
}
overlay_entry_release_ov( op, e, 0, on );
for ( rdle = rdli->rdli_entry ; rdle ; rdle = rdle->rdle_next ) {
is_olddn = 0;
is_newdn = 0;
ldap_pvt_thread_mutex_lock( &rdle->rdle_mutex );
if ( overlay_entry_get_ov( op, &rdle->rdle_ndn, NULL, NULL, 0, &group, on ) !=
LDAP_SUCCESS || group == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_response MODIFY cannot get entry for <%s>\n",
rdle->rdle_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
a = attrs_find( group->e_attrs, rdle->rdle_def->rdld_member_ad );
if ( a != NULL ) {
if ( value_find_ex( rdle->rdle_def->rdld_member_ad,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a->a_nvals, &op->o_req_ndn, op->o_tmpmemctx ) == 0 )
{
is_olddn = 1;
}
}
overlay_entry_release_ov( op, group, 0, on );
for ( rdlf = rdle->rdle_filter ; rdlf ; rdlf = rdlf->rdlf_next ) {
if ( dnIsSuffix( &op->o_req_ndn, &rdlf->rdlf_ndn ) ) {
if ( test_filter( op, e, rdlf->rdlf_filter ) == LDAP_COMPARE_TRUE ) {
is_newdn = 1;
break;
}
}
}
if ( is_olddn == 1 && is_newdn == 0 ) {
rdynlist_delete_member_from_group( op, &op->o_req_dn, &op->o_req_ndn, rdle );
} else
if ( is_olddn == 0 && is_newdn == 1 ) {
rdynlist_add_member_to_group( op, &op->o_req_dn, &op->o_req_ndn, rdle );
}
ldap_pvt_thread_mutex_unlock( &rdle->rdle_mutex );
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
}
}
return SLAP_CB_CONTINUE;
}
static int
rdynlist_modify_entry( Operation *op, SlapReply *rs)
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
rdynlist_info_t *rdli = (rdynlist_info_t *)on->on_bi.bi_private;
rdynlist_def_t *rdld = rdli->rdli_def;
rdynlist_entry_t *rdle = rdli->rdli_entry;
Entry *e;
Attribute *a;
if ( get_manageDSAit( op ) ) {
return SLAP_CB_CONTINUE;
}
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_modify_entry <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
if ( overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on ) !=
LDAP_SUCCESS || e == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_modify_entry cannot get entry for <%s>\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
a = attrs_find( e->e_attrs, slap_schema.si_ad_objectClass );
overlay_entry_release_ov( op, e, 0, on );
if ( a == NULL ) {
Debug( LDAP_DEBUG_TRACE, "rdynlist_modify_entry entry <%s> has no objectClass\n", op->o_req_dn.bv_val, 0, 0);
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
for ( ; rdld; rdld = rdld->rdld_next ) {
if ( value_find_ex( slap_schema.si_ad_objectClass,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a->a_nvals, &rdld->rdld_oc->soc_cname,
op->o_tmpmemctx ) == 0 )
{
Modifications *m;
int match = 1;
m = op->orm_modlist;
for ( ; rdle ; rdle = rdle->rdle_next ) {
dnMatch( &match, 0, NULL, NULL, &op->o_req_ndn, &rdle->rdle_ndn );
if ( match == 0 ) {
for ( ; m ; m = m->sml_next ) {
if ( m->sml_desc == rdle->rdle_def->rdld_member_ad ) {
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
Debug( LDAP_DEBUG_TRACE, "rdynlist_modify_entry attempted to modify group's <%s> member attribute\n", op->o_req_dn.bv_val, 0, 0);
send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to modify dynamic group member attribute");
return LDAP_CONSTRAINT_VIOLATION;
}
}
break;
}
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return SLAP_CB_CONTINUE;
}
static int
rdynlist_build_def_filter( rdynlist_def_t *rdld, Operation *op )
{
char *ptr;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_build_def_filter\n", 0, 0, 0);
op->ors_filterstr.bv_len = STRLENOF( "(=)" )
+ slap_schema.si_ad_objectClass->ad_cname.bv_len
+ rdld->rdld_oc->soc_cname.bv_len;
ptr = op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx );
*ptr++ = '(';
ptr = lutil_strcopy( ptr, slap_schema.si_ad_objectClass->ad_cname.bv_val );
*ptr++ = '=';
ptr = lutil_strcopy( ptr, rdld->rdld_oc->soc_cname.bv_val );
*ptr++ = ')';
*ptr = '\0';
op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val );
assert( op->ors_filterstr.bv_len == ptr - op->ors_filterstr.bv_val );
return 0;
}
enum {
RDL_ATTRSET = 1,
RDL_LAST
};
static ConfigDriver rdl_cfgen;
static ConfigTable rdlcfg[] = {
{ "rdynlist-attrset", "group-oc> <URL-ad> <member-ad",
3, 4, 0, ARG_MAGIC|RDL_ATTRSET, rdl_cfgen,
"( OLcfgOvAt:20.1 NAME 'olcRDLattrSet' "
"DESC 'Really dynamic list: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString "
"X-ORDERED 'VALUES' )",
NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
static ConfigOCs rdlocs[] = {
{ "( OLcfgOvOc:20.1 "
"NAME 'olcReallyDynamicList' "
"DESC 'Really dynamic list configuration' "
"SUP olcOverlayConfig "
"MAY olcRDLattrSet )",
Cft_Overlay, rdlcfg, NULL, NULL },
{ NULL, 0, NULL }
};
static int
rdl_cfgen( ConfigArgs *c )
{
slap_overinst *on = (slap_overinst *)c->bi;
rdynlist_info_t *rdli = (rdynlist_info_t *)on->on_bi.bi_private;
rdynlist_def_t *rdld;
rdynlist_entry_t *rdle;
int rc = 0, i;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_cfgen\n", 0, 0, 0);
if( rdli == NULL ) {
rdli = (rdynlist_info_t*)ch_calloc( 1, sizeof(rdynlist_info_t) );
ldap_pvt_thread_mutex_init( &rdli->rdli_mutex );
on->on_bi.bi_private = (void *)rdli;
}
rdld = rdli->rdli_def;
rdle = rdli->rdli_entry;
if ( c->op == SLAP_CONFIG_EMIT ) {
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
for ( i = 0 ; rdld ; i++, rdld = rdld->rdld_next ) {
struct berval bv;
char *ptr = c->cr_msg;
assert(rdld->rdld_oc != NULL);
assert(rdld->rdld_member_url_ad != NULL);
assert(rdld->rdld_member_ad != NULL);
ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
SLAP_X_ORDERED_FMT "%s %s %s", i,
rdld->rdld_oc->soc_cname.bv_val,
rdld->rdld_member_url_ad->ad_cname.bv_val,
rdld->rdld_member_ad->ad_cname.bv_val );
bv.bv_val = c->cr_msg;
bv.bv_len = ptr - bv.bv_val;
value_add_one ( &c->rvalue_vals, &bv );
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return rc;
}else if ( c->op == LDAP_MOD_DELETE ) {
if ( c->valx < 0) {
rdynlist_def_t *rdld_next;
rdynlist_entry_t *rdle_next;
rdynlist_filter_t *rdlf = rdle->rdle_filter,
*rdlf_next;
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
for ( rdld_next = rdld; rdld_next; rdld = rdld_next ) {
rdld_next = rdld->rdld_next;
ch_free( rdld );
}
for ( rdle_next = rdle ; rdle_next ; rdle = rdle_next ) {
rdle_next = rdle->rdle_next;
ch_free( rdle->rdle_dn.bv_val );
ch_free( rdle->rdle_ndn.bv_val );
for( rdlf_next = rdlf ; rdlf_next ; rdlf = rdlf_next ){
rdlf_next = rdlf->rdlf_next;
filter_free( rdlf->rdlf_filter );
ch_free( rdlf->rdlf_filterstr.bv_val );
ch_free( rdlf->rdlf_dn.bv_val );
ch_free( rdlf->rdlf_ndn.bv_val );
}
ldap_pvt_thread_mutex_init( &rdle->rdle_mutex );
ch_free( rdle );
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
ldap_pvt_thread_mutex_destroy( &rdli->rdli_mutex );
ch_free( rdli );
on->on_bi.bi_private = NULL;
} else {
rdynlist_def_t **rdldp;
rdynlist_entry_t *rdle_next, *rdle_prev;
rdynlist_filter_t *rdlf,
*rdlf_next;
struct berval *bv;
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
for ( i = 0, rdldp = &rdli->rdli_def;
i < c->valx; i++ )
{
if ( *rdldp == NULL) {
return 1;
}
rdldp = &(*rdldp)->rdld_next;
}
rdld = *rdldp;
*rdldp = rdld->rdld_next;
for ( rdle_next = rdle , rdle_prev = NULL ; rdle_next ; rdle_prev = rdle, rdle = rdle_next ) {
rdle_next = rdle->rdle_next;
if( rdle->rdle_def == rdld ) {
rdlf = rdle->rdle_filter;
ch_free( rdle->rdle_dn.bv_val );
ch_free( rdle->rdle_ndn.bv_val );
for ( rdlf_next = rdlf; rdlf_next ; rdlf = rdlf_next ) {
rdlf_next = rdlf->rdlf_next;
filter_free( rdlf->rdlf_filter );
ch_free( rdlf->rdlf_filterstr.bv_val );
ch_free( rdlf->rdlf_dn.bv_val );
ch_free( rdlf->rdlf_ndn.bv_val );
}
ldap_pvt_thread_mutex_destroy( &rdle->rdle_mutex );
ch_free( rdle );
rdle = rdle_prev;
if( rdle_prev != NULL ) {
rdle_prev->rdle_next = rdle_next;
}
}
}
ch_free( rdld );
rdld = rdli->rdli_def;
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
}
return rc;
}
switch(c->type){
case RDL_ATTRSET: {
rdynlist_def_t **rdldp,
*rdld_next = NULL;
ObjectClass *oc = NULL;
AttributeDescription *member_url_ad = NULL,
*member_ad = NULL;
const char *text;
oc = oc_find( c->argv[ 1 ] );
if( oc == NULL ){
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"rdynlist-attrset <oc> <URL-ad> <member-ad>\": "
"unable to find ObjectClass \"%s\"",
c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
rc = slap_str2ad( c->argv[ 2 ], &member_url_ad, &text );
if( rc != LDAP_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"rdynlist-attrset <oc> <URL-ad> <member-ad>\": "
"unable to find AttributeDescription \"%s\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
if( !is_at_subtype( member_url_ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"rdynlist-attrset <oc> <URL-ad> <member-ad>\": "
"AttributeDescription \"%s\" ",
"must be of a subtype \"labeledURI\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
rc = slap_str2ad( c->argv[3], &member_ad, &text );
if( rc != LDAP_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"rdynlist-attrset <oc> <URL-ad> <member-ad>\": "
"unable to find AttributeDescription \"%s\"",
c->argv[ 3 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
for ( rdldp = &rdli->rdli_def ; *rdldp ; rdldp = &(*rdldp)->rdld_next ) {
/* The same URL attribute / member attribute pair
* cannot be repeated */
if ( (*rdldp)->rdld_member_url_ad == member_url_ad && (*rdldp)->rdld_member_ad == member_ad ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"rdynlist-attrset <oc> <URL-ad> <member-ad>\": "
"URL attributeDescription \"%s\" already mapped",
member_ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
/* return 1; //warning*/
}
}
if ( c->valx > 0 ) {
int i;
for ( i = 0, rdldp = &rdli->rdli_def ;
i < c->valx; i++ )
{
if ( *rdldp == NULL ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"rdynlist-attrset <oc> <URL-ad> <member-ad>\": "
"invalid index {%d}",
c->valx );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return 1;
}
rdldp = &(*rdldp)->rdld_next;
}
rdld_next = *rdldp;
} else {
for ( rdldp = &rdli->rdli_def; *rdldp;
rdldp = &(*rdldp)->rdld_next )
/* goto last */;
}
*rdldp = (rdynlist_def_t *)ch_calloc( 1, sizeof(rdynlist_info_t));
(*rdldp)->rdld_oc = oc;
(*rdldp)->rdld_member_url_ad = member_url_ad;
(*rdldp)->rdld_member_ad = member_ad;
(*rdldp)->rdld_next = rdld_next;
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
} break;
default:
rc = 1;
break;
}
return rc;
}
static int
rdynlist_db_open(
BackendDB *be,
ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info,
*on_bd;
rdynlist_info_t *rdli = on->on_bi.bi_private;
rdynlist_def_t *rdld;
rdynlist_sc_t rdls;
Operation *op;
SlapReply rs = { REP_RESULT };
slap_callback cb = { 0 };
void *thrctx = ldap_pvt_thread_pool_context();
Connection conn = { 0 };
OperationBuffer opbuf;
BerValue bv;
char *ptr;
int rc = 0;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_db_open\n", 0, 0, 0);
connection_fake_init( &conn, &opbuf, thrctx );
op = &opbuf.ob_op;
op->ors_attrsonly = 0;
op->o_tag = LDAP_REQ_SEARCH;
op->o_dn = be->be_rootdn;
op->o_ndn = be->be_rootndn;
op->o_req_dn = be->be_suffix[0];
op->o_req_ndn = be->be_nsuffix[0];
op->ors_scope = LDAP_SCOPE_SUBTREE;
op->ors_deref = LDAP_DEREF_NEVER;
op->ors_limit = NULL;
op->ors_tlimit = SLAP_NO_LIMIT;
op->ors_slimit = SLAP_NO_LIMIT;
op->ors_attrs = slap_anlist_no_attrs;
op->o_bd = select_backend(&op->o_req_ndn, 0);
ldap_pvt_thread_mutex_lock( &rdli->rdli_mutex );
for (rdld = rdli->rdli_def ; rdld ; rdld = rdld->rdld_next) {
rdynlist_build_def_filter(rdld, op);
rdls.rdls_info = rdli;
rdls.rdls_def = rdld;
cb.sc_private = &rdls;
cb.sc_response = rdynlist_group_add_cb;
cb.sc_cleanup = NULL;
cb.sc_next = NULL;
op->o_callback = &cb;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
op->o_bd->be_search( op, &rs );
op->o_bd->bd_info = (BackendInfo *)on; /* FIXME: needed? */
filter_free_x( op, op->ors_filter );
op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
}
ldap_pvt_thread_mutex_unlock( &rdli->rdli_mutex );
return 0;
}
static int
rdynlist_db_destroy(
BackendDB *be,
ConfigReply *cr )
{
slap_overinst *on = (slap_overinst *) be->bd_info;
Debug( LDAP_DEBUG_TRACE, "==> rdynlist_db_destroy\n", 0, 0, 0);
if ( on->on_bi.bi_private ) {
rdynlist_info_t *rdli = on->on_bi.bi_private;
rdynlist_def_t *rdld = rdli->rdli_def,
*rdld_next;
rdynlist_entry_t *rdle = rdli->rdli_entry,
*rdle_next;
rdynlist_filter_t *rdlf, *rdlf_next;
for ( rdld_next = rdld; rdld_next; rdld = rdld_next ) {
rdld_next = rdld->rdld_next;
ch_free( rdld );
}
for ( rdle_next = rdle; rdle_next; rdle = rdle_next ) {
rdle_next = rdle->rdle_next;
ch_free( rdle->rdle_dn.bv_val );
ch_free( rdle->rdle_ndn.bv_val );
rdlf = rdle->rdle_filter;
for ( rdlf_next = rdlf; rdlf_next; rdlf = rdlf_next ) {
rdlf_next = rdlf->rdlf_next;
filter_free( rdlf->rdlf_filter );
ch_free( rdlf->rdlf_filterstr.bv_val );
ch_free( rdlf->rdlf_dn.bv_val );
ch_free( rdlf->rdlf_ndn.bv_val );
ch_free( rdlf );
}
ldap_pvt_thread_mutex_destroy( &rdle->rdle_mutex );
ch_free( rdle );
}
ldap_pvt_thread_mutex_destroy( &rdli->rdli_mutex );
ch_free( rdli );
}
return 0;
}
static slap_overinst rdynlist = { { NULL } };
#if SLAPD_OVER_RDYNLIST == SLAPD_MOD_DYNAMIC
static
#endif /* SLAPD_OVER_RDYNLIST == SLAPD_MOD_DYNAMIC */
int
rdynlist_initialize(void)
{
int rc = 0;
rdynlist.on_bi.bi_type = "rdynlist";
rdynlist.on_bi.bi_db_config = config_generic_wrapper;
rdynlist.on_bi.bi_db_open = rdynlist_db_open;
rdynlist.on_bi.bi_db_destroy = rdynlist_db_destroy;
rdynlist.on_bi.bi_op_add = rdynlist_add_entry;
rdynlist.on_bi.bi_op_delete = rdynlist_delete_entry;
rdynlist.on_bi.bi_op_modify = rdynlist_modify_entry;
rdynlist.on_response = rdynlist_response;
rdynlist.on_bi.bi_cf_ocs = rdlocs;
rc = config_register_schema( rdlcfg, rdlocs );
if ( rc ) {
return rc;
}
return overlay_register( &rdynlist );
}
#if SLAPD_OVER_RDYNLIST == SLAPD_MOD_DYNAMIC
int
init_module( int argc, char *argv[] )
{
return rdynlist_initialize();
}
#endif
#endif /* SLAPD_OVER_RDYNLIST */