[Fedora-directory-commits] ldapserver/ldap/servers/plugins/memberof memberof.h, NONE, 1.1 memberof_config.c, NONE, 1.1 memberof.c, 1.8, 1.9
Nathan Kinder (nkinder)
fedora-directory-commits at redhat.com
Thu Jun 19 15:18:22 UTC 2008
Author: nkinder
Update of /cvs/dirsec/ldapserver/ldap/servers/plugins/memberof
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv7009/ldap/servers/plugins/memberof
Modified Files:
memberof.c
Added Files:
memberof.h memberof_config.c
Log Message:
Resolves: 450989
Summary: Make memberOf plug-in attributes configurable.
--- NEW FILE memberof.h ---
/** BEGIN COPYRIGHT BLOCK
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; version 2 of the License.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA.
*
* In addition, as a special exception, Red Hat, Inc. gives You the additional
* right to link the code of this Program with code not covered under the GNU
* General Public License ("Non-GPL Code") and to distribute linked combinations
* including the two, subject to the limitations in this paragraph. Non-GPL Code
* permitted under this exception must only link to the code of this Program
* through those well defined interfaces identified in the file named EXCEPTION
* found in the source code files (the "Approved Interfaces"). The files of
* Non-GPL Code may instantiate templates or use macros or inline functions from
* the Approved Interfaces without causing the resulting work to be covered by
* the GNU General Public License. Only Red Hat, Inc. may make changes or
* additions to the list of Approved Interfaces. You must obey the GNU General
* Public License in all respects for all of the Program code and other code used
* in conjunction with the Program except the Non-GPL Code covered by this
* exception. If you modify this file, you may extend this exception to your
* version of the file, but you are not obligated to do so. If you do not wish to
* provide this exception without modification, you must delete this exception
* statement from your version and license this file solely under the GPL without
* exception.
*
*
* Copyright (C) 2008 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/*
* memberof.h - memberOf shared definitions
*
*/
#ifndef _MEMBEROF_H_
#define _MEMBEROF_H_
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include "portable.h"
#include "slapi-plugin.h"
#include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
#include "dirver.h"
#include <nspr.h>
/* Private API: to get SLAPI_DSE_RETURNTEXT_SIZE, DSE_FLAG_PREOP, and DSE_FLAG_POSTOP */
#include "slapi-private.h"
/*
* macros
*/
#define MEMBEROF_PLUGIN_SUBSYSTEM "memberof-plugin" /* used for logging */
#define MEMBEROF_GROUP_ATTR "memberOfGroupAttr"
#define MEMBEROF_ATTR "memberOfAttr"
/*
* structs
*/
typedef struct memberofconfig {
char *groupattr;
char *memberof_attr;
Slapi_Filter *group_filter;
Slapi_Attr *group_slapiattr;
} MemberOfConfig;
/*
* functions
*/
int memberof_config(Slapi_Entry *config_e);
void memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src);
MemberOfConfig *memberof_get_config();
void memberof_lock();
void memberof_unlock();
void memberof_rlock_config();
void memberof_wlock_config();
void memberof_unlock_config();
#endif /* _MEMBEROF_H_ */
--- NEW FILE memberof_config.c ---
/** BEGIN COPYRIGHT BLOCK
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; version 2 of the License.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA.
*
* In addition, as a special exception, Red Hat, Inc. gives You the additional
* right to link the code of this Program with code not covered under the GNU
* General Public License ("Non-GPL Code") and to distribute linked combinations
* including the two, subject to the limitations in this paragraph. Non-GPL Code
* permitted under this exception must only link to the code of this Program
* through those well defined interfaces identified in the file named EXCEPTION
* found in the source code files (the "Approved Interfaces"). The files of
* Non-GPL Code may instantiate templates or use macros or inline functions from
* the Approved Interfaces without causing the resulting work to be covered by
* the GNU General Public License. Only Red Hat, Inc. may make changes or
* additions to the list of Approved Interfaces. You must obey the GNU General
* Public License in all respects for all of the Program code and other code used
* in conjunction with the Program except the Non-GPL Code covered by this
* exception. If you modify this file, you may extend this exception to your
* version of the file, but you are not obligated to do so. If you do not wish to
* provide this exception without modification, you must delete this exception
* statement from your version and license this file solely under the GPL without
* exception.
*
*
* Copyright (C) 2008 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK **/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/*
* memberof_config.c - configuration-related code for memberOf plug-in
*
*/
#include <plstr.h>
#include "memberof.h"
#define MEMBEROF_CONFIG_FILTER "(objectclass=*)"
/*
* The configuration attributes are contained in the plugin entry e.g.
* cn=MemberOf Plugin,cn=plugins,cn=config
*
* Configuration is a two step process. The first pass is a validation step which
* occurs pre-op - check inputs and error out if bad. The second pass actually
* applies the changes to the run time config.
*/
/*
* function prototypes
*/
static int memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg);
static int memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg);
static int memberof_search (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg)
{
return SLAPI_DSE_CALLBACK_OK;
}
/*
* static variables
*/
/* This is the main configuration which is updated from dse.ldif. The
* config will be copied when it is used by the plug-in to prevent it
* being changed out from under a running memberOf operation. */
static MemberOfConfig theConfig;
static PRRWLock *memberof_config_lock = 0;
static int inited = 0;
static int dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg)
{
*returncode = LDAP_UNWILLING_TO_PERFORM;
return SLAPI_DSE_CALLBACK_ERROR;
}
/*
* memberof_config()
*
* Read configuration and create a configuration data structure.
* This is called after the server has configured itself so we can
* perform checks with regards to suffixes if it ever becomes
* necessary.
* Returns an LDAP error code (LDAP_SUCCESS if all goes well).
*/
int
memberof_config(Slapi_Entry *config_e)
{
int returncode = LDAP_SUCCESS;
char returntext[SLAPI_DSE_RETURNTEXT_SIZE];
if ( inited ) {
slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"only one memberOf plugin instance can be used\n" );
return( LDAP_PARAM_ERROR );
}
/* initialize the RW lock to protect the main config */
memberof_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "memberof_config_lock");
/* initialize fields */
if (SLAPI_DSE_CALLBACK_OK == memberof_validate_config(NULL, NULL, config_e,
&returncode, returntext, NULL)) {
memberof_apply_config(NULL, NULL, config_e,
&returncode, returntext, NULL);
}
/* config DSE must be initialized before we get here */
if (returncode == LDAP_SUCCESS) {
const char *config_dn = slapi_entry_get_dn_const(config_e);
slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP,
config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
memberof_validate_config,NULL);
slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP,
config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
memberof_apply_config,NULL);
slapi_config_register_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP,
config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
dont_allow_that, NULL);
slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP,
config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
dont_allow_that, NULL);
slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
config_dn, LDAP_SCOPE_BASE, MEMBEROF_CONFIG_FILTER,
memberof_search,NULL);
}
inited = 1;
if (returncode != LDAP_SUCCESS) {
slapi_log_error(SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"Error %d: %s\n", returncode, returntext);
}
return returncode;
}
/*
* memberof_validate_config()
*
* Validate the pending changes in the e entry.
*/
static int
memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg)
{
Slapi_Attr *attr = NULL;
*returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */
/* Make sure both the group attr and the memberOf attr
* config atributes are supplied. We don't care about &attr
* here, but slapi_entry_attr_find() requires us to pass it. */
if (!slapi_entry_attr_find(e, MEMBEROF_GROUP_ATTR, &attr) &&
!slapi_entry_attr_find(e, MEMBEROF_ATTR, &attr))
{
*returncode = LDAP_SUCCESS;
} else {
PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
"The %s and %s configuration attributes must be provided",
MEMBEROF_GROUP_ATTR, MEMBEROF_ATTR);
}
if (*returncode != LDAP_SUCCESS)
{
return SLAPI_DSE_CALLBACK_ERROR;
}
else
{
return SLAPI_DSE_CALLBACK_OK;
}
}
/*
* memberof_apply_config()
*
* Apply the pending changes in the e entry to our config struct.
* memberof_validate_config() must have already been called.
*/
static int
memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
int *returncode, char *returntext, void *arg)
{
char *groupattr = NULL;
char *memberof_attr = NULL;
char *filter_str = NULL;
*returncode = LDAP_SUCCESS;
groupattr = slapi_entry_attr_get_charptr(e, MEMBEROF_GROUP_ATTR);
memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR);
/* We want to be sure we don't change the config in the middle of
* a memberOf operation, so we obtain an exclusive lock here */
memberof_wlock_config();
if (!theConfig.groupattr ||
(groupattr && PL_strcmp(theConfig.groupattr, groupattr))) {
slapi_ch_free_string(&theConfig.groupattr);
theConfig.groupattr = groupattr;
groupattr = NULL; /* config now owns memory */
/* We allocate a Slapi_Attr using the groupattr for
* convenience in our memberOf comparison functions */
slapi_attr_free(&theConfig.group_slapiattr);
theConfig.group_slapiattr = slapi_attr_new();
slapi_attr_init(theConfig.group_slapiattr, theConfig.groupattr);
/* The filter is based off of the groupattr, so we
* update it here too. */
slapi_filter_free(theConfig.group_filter, 1);
filter_str = slapi_ch_smprintf("(%s=*)", theConfig.groupattr);
theConfig.group_filter = slapi_str2filter(filter_str);
slapi_ch_free_string(&filter_str);
}
if (!theConfig.memberof_attr ||
(memberof_attr && PL_strcmp(theConfig.memberof_attr, memberof_attr))) {
slapi_ch_free_string(&theConfig.memberof_attr);
theConfig.memberof_attr = memberof_attr;
memberof_attr = NULL; /* config now owns memory */
}
/* release the lock */
memberof_unlock_config();
slapi_ch_free_string(&groupattr);
slapi_ch_free_string(&memberof_attr);
if (*returncode != LDAP_SUCCESS)
{
return SLAPI_DSE_CALLBACK_ERROR;
}
else
{
return SLAPI_DSE_CALLBACK_OK;
}
}
/*
* memberof_copy_config()
*
* Makes a copy of the config in src. This function will free the
* elements of dest if they already exist. This should only be called
* if you hold the memberof config lock if src was obtained with
* memberof_get_config().
*/
void
memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src)
{
if (dest && src)
{
/* Check if the copy is already up to date */
if (!dest->groupattr || (src->groupattr
&& PL_strcmp(dest->groupattr, src->groupattr)))
{
slapi_ch_free_string(&dest->groupattr);
dest->groupattr = slapi_ch_strdup(src->groupattr);
slapi_filter_free(dest->group_filter, 1);
dest->group_filter = slapi_filter_dup(src->group_filter);
slapi_attr_free(&dest->group_slapiattr);
dest->group_slapiattr = slapi_attr_dup(src->group_slapiattr);
}
if (!dest->memberof_attr || (src->memberof_attr
&& PL_strcmp(dest->memberof_attr, src->memberof_attr)))
{
slapi_ch_free_string(&dest->memberof_attr);
dest->memberof_attr = slapi_ch_strdup(src->memberof_attr);
}
}
}
/*
* memberof_get_config()
*
* Returns a pointer to the main config. You should call
* memberof_rlock_config() first so the main config doesn't
* get modified out from under you.
*/
MemberOfConfig *
memberof_get_config()
{
return &theConfig;
}
/*
* memberof_rlock_config()
*
* Gets a non-exclusive lock on the main config. This will
* prevent the config from being changed out from under you
* while you read it, but it will still allow other threads
* to read the config at the same time.
*/
void
memberof_rlock_config()
{
PR_RWLock_Rlock(memberof_config_lock);
}
/*
* memberof_wlock_config()
*
* Gets an exclusive lock on the main config. This should
* be called if you need to write to the main config.
*/
void
memberof_wlock_config()
{
PR_RWLock_Wlock(memberof_config_lock);
}
/*
* memberof_unlock_config()
*
* Unlocks the main config.
*/
void
memberof_unlock_config()
{
PR_RWLock_Unlock(memberof_config_lock);
}
Index: memberof.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/plugins/memberof/memberof.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- memberof.c 9 Jun 2008 21:43:59 -0000 1.8
+++ memberof.c 19 Jun 2008 15:18:20 -0000 1.9
@@ -72,18 +72,14 @@
#include "string.h"
#include "nspr.h"
-#define MEMBEROF_GROUP_ATTR "member"
-#define MEMBEROF_ATTR "memberof"
-#define MEMBEROF_GROUP_ATTR_IS_DN 1
-#define MEMBEROF_GROUP_FILTER "(" MEMBEROF_GROUP_ATTR "=*)"
+#include "memberof.h"
-#define MEMBEROF_PLUGIN_SUBSYSTEM "memberof-plugin" /* used for logging */
static Slapi_PluginDesc pdesc = { "memberof", PLUGIN_MAGIC_VENDOR_STR,
PRODUCTTEXT, "memberof plugin" };
static void* _PluginID = NULL;
-static Slapi_Filter *memberof_group_filter = NULL;
static Slapi_Mutex *memberof_operation_lock = 0;
+MemberOfConfig *qsortConfig = 0;
typedef struct _memberofstringll
{
@@ -107,47 +103,60 @@
/* supporting cast */
static int memberof_oktodo(Slapi_PBlock *pb);
static char *memberof_getdn(Slapi_PBlock *pb);
-static int memberof_modop_one(Slapi_PBlock *pb, int mod_op, char *op_this, char *op_to);
-static int memberof_modop_one_r(Slapi_PBlock *pb, int mod_op, char *group_dn,
- char *op_this, char *op_to, memberofstringll *stack);
-static int memberof_add_one(Slapi_PBlock *pb, char *addthis, char *addto);
-static int memberof_del_one(Slapi_PBlock *pb, char *delthis, char *delfrom);
-static int memberof_mod_smod_list(Slapi_PBlock *pb, int mod, char *groupdn,
- Slapi_Mod *smod);
-static int memberof_add_smod_list(Slapi_PBlock *pb, char *groupdn, Slapi_Mod *smod);
-static int memberof_del_smod_list(Slapi_PBlock *pb, char *groupdn, Slapi_Mod *smod);
-static int memberof_mod_attr_list(Slapi_PBlock *pb, int mod, char *groupdn,
- Slapi_Attr *attr);
-static int memberof_mod_attr_list_r(Slapi_PBlock *pb, int mod, char *group_dn,
- char *op_this, Slapi_Attr *attr, memberofstringll *stack);
-static int memberof_add_attr_list(Slapi_PBlock *pb, char *groupdn, Slapi_Attr *attr);
-static int memberof_del_attr_list(Slapi_PBlock *pb, char *groupdn, Slapi_Attr *attr);
-static int memberof_moddn_attr_list(Slapi_PBlock *pb, char *pre_dn, char *post_dn,
- Slapi_Attr *attr);
-static int memberof_replace_list(Slapi_PBlock *pb, char *group_dn);
+static int memberof_modop_one(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
+ char *op_this, char *op_to);
+static int memberof_modop_one_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
+ char *group_dn, char *op_this, char *op_to, memberofstringll *stack);
+static int memberof_add_one(Slapi_PBlock *pb, MemberOfConfig *config, char *addthis,
+ char *addto);
+static int memberof_del_one(Slapi_PBlock *pb, MemberOfConfig *config, char *delthis,
+ char *delfrom);
+static int memberof_mod_smod_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
+ char *groupdn, Slapi_Mod *smod);
+static int memberof_add_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *groupdn, Slapi_Mod *smod);
+static int memberof_del_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *groupdn, Slapi_Mod *smod);
+static int memberof_mod_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
+ char *groupdn, Slapi_Attr *attr);
+static int memberof_mod_attr_list_r(Slapi_PBlock *pb, MemberOfConfig *config,
+ int mod, char *group_dn, char *op_this, Slapi_Attr *attr, memberofstringll *stack);
+static int memberof_add_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *groupdn, Slapi_Attr *attr);
+static int memberof_del_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *groupdn, Slapi_Attr *attr);
+static int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *pre_dn, char *post_dn, Slapi_Attr *attr);
+static int memberof_replace_list(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn);
static void memberof_set_plugin_id(void * plugin_id);
static void *memberof_get_plugin_id();
-static int memberof_compare(const void *a, const void *b);
+static int memberof_compare(MemberOfConfig *config, const void *a, const void *b);
+static int memberof_qsort_compare(const void *a, const void *b);
static void memberof_load_array(Slapi_Value **array, Slapi_Attr *attr);
-static Slapi_Filter *memberof_string2filter(char *strfilter);
-static int memberof_is_legit_member(Slapi_PBlock *pb, char *group_dn,
- char *op_this, char *op_to, memberofstringll *stack);
-static int memberof_del_dn_from_groups(Slapi_PBlock *pb, char *dn);
+static int memberof_is_legit_member(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *group_dn, char *op_this, char *op_to, memberofstringll *stack);
+static int memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn);
static int memberof_call_foreach_dn(Slapi_PBlock *pb, char *dn,
char *type, plugin_search_entry_callback callback, void *callback_data);
-static int memberof_is_direct_member(Slapi_Value *groupdn, Slapi_Value *memberdn);
-static int memberof_is_member(Slapi_Value *groupdn, Slapi_Value *memberdn);
-static int memberof_test_membership(Slapi_PBlock *pb, char *group_dn);
+static int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn,
+ Slapi_Value *memberdn);
+static int memberof_is_member(MemberOfConfig *config, Slapi_Value *groupdn,
+ Slapi_Value *memberdn);
+static int memberof_is_member_r(MemberOfConfig *config, Slapi_Value *groupdn,
+ Slapi_Value *memberdn, memberofstringll *stack);
+static int memberof_test_membership(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *group_dn);
static int memberof_test_membership_callback(Slapi_Entry *e, void *callback_data);
static int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data);
static int memberof_replace_dn_type_callback(Slapi_Entry *e, void *callback_data);
-static int memberof_replace_dn_from_groups(Slapi_PBlock *pb, char *pre_dn, char *post_dn);
-static int memberof_modop_one_replace_r(Slapi_PBlock *pb, int mod_op, char *group_dn,
- char *op_this, char *replace_with, char *op_to, memberofstringll *stack);
-static void memberof_lock();
-static void memberof_unlock();
+static int memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *pre_dn, char *post_dn);
+static int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config,
+ int mod_op, char *group_dn, char *op_this, char *replace_with, char *op_to,
+ memberofstringll *stack);
static int memberof_add_groups_search_callback(Slapi_Entry *e, void *callback_data);
-static int memberof_add_membership(Slapi_PBlock *pb, char *op_this, char *op_to);
+static int memberof_add_membership(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *op_this, char *op_to);
static int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
Slapi_Entry *eAfter, int *returncode, char *returntext,
void *arg);
@@ -155,7 +164,7 @@
static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
const char *default_val);
static void memberof_fixup_task_thread(void *arg);
-static int memberof_fix_memberof(char *dn, char *filter_str);
+static int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str);
static int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data);
@@ -223,20 +232,31 @@
int memberof_postop_start(Slapi_PBlock *pb)
{
int rc = 0;
+ Slapi_Entry *config_e = NULL; /* entry containing plugin config */
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"--> memberof_postop_start\n" );
- memberof_group_filter = memberof_string2filter(MEMBEROF_GROUP_FILTER);
-
memberof_operation_lock = slapi_new_mutex();
-
- if(0 == memberof_group_filter || 0 == memberof_operation_lock)
+ if(0 == memberof_operation_lock)
{
rc = -1;
goto bail;
}
+ if ( slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &config_e ) != 0 ) {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "missing config entry\n" );
+ rc = -1;
+ goto bail;
+ }
+
+ if (( rc = memberof_config( config_e )) != LDAP_SUCCESS ) {
+ slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
+ "configuration failed (%s)\n", ldap_err2string( rc ));
+ return( -1 );
+ }
+
rc = slapi_task_register_handler("memberof task", memberof_task_add);
if(rc)
{
@@ -292,6 +312,7 @@
int memberof_postop_del(Slapi_PBlock *pb)
{
int ret = 0;
+ MemberOfConfig configCopy = {0, 0, 0, 0};
char *dn;
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
@@ -302,22 +323,31 @@
struct slapi_entry *e = NULL;
slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &e );
-
- memberof_lock();
+ /* We need to get the config lock first. Trying to get the
+ * config lock after we already hold the op lock can cause
+ * a deadlock. */
+ memberof_rlock_config();
+ /* copy config so it doesn't change out from under us */
+ memberof_copy_config(&configCopy, memberof_get_config());
+ memberof_unlock_config();
+
+ /* get the memberOf operation lock */
+ memberof_lock();
+
/* remove this group DN from the
* membership lists of groups
*/
- memberof_del_dn_from_groups(pb, dn);
+ memberof_del_dn_from_groups(pb, &configCopy, dn);
/* is the entry of interest as a group? */
- if(e && !slapi_filter_test_simple(e, memberof_group_filter))
+ if(e && !slapi_filter_test_simple(e, configCopy.group_filter))
{
Slapi_Attr *attr = 0;
- if(0 == slapi_entry_attr_find(e, MEMBEROF_GROUP_ATTR, &attr))
+ if(0 == slapi_entry_attr_find(e, configCopy.groupattr, &attr))
{
- memberof_del_attr_list(pb, dn, attr);
+ memberof_del_attr_list(pb, &configCopy, dn, attr);
}
}
@@ -335,12 +365,12 @@
char *type;
} del_dn_data;
-int memberof_del_dn_from_groups(Slapi_PBlock *pb, char *dn)
+int memberof_del_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config, char *dn)
{
- del_dn_data data = {dn, MEMBEROF_GROUP_ATTR};
+ del_dn_data data = {dn, config->groupattr};
return memberof_call_foreach_dn(pb, dn,
- MEMBEROF_GROUP_ATTR, memberof_del_dn_type_callback, &data);
+ config->groupattr, memberof_del_dn_type_callback, &data);
}
int memberof_del_dn_type_callback(Slapi_Entry *e, void *callback_data)
@@ -408,12 +438,7 @@
if(base_sdn)
{
- int filter_size =
- (strlen(type) +
- strlen(dn) + 4); /* 4 for (=) + null */
- filter_str = (char*)slapi_ch_malloc(filter_size);
-
- sprintf(filter_str, "(%s=%s)", type, dn);
+ filter_str = slapi_ch_smprintf("(%s=%s)", type, dn);
}
if(filter_str)
@@ -451,10 +476,13 @@
if(memberof_oktodo(pb))
{
+ MemberOfConfig *mainConfig = 0;
+ MemberOfConfig configCopy = {0, 0, 0, 0};
struct slapi_entry *pre_e = NULL;
struct slapi_entry *post_e = NULL;
char *pre_dn = 0;
char *post_dn = 0;
+ int interested = 0;
slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &pre_e );
slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &post_e );
@@ -466,8 +494,18 @@
}
/* is the entry of interest? */
- if(pre_dn && post_dn &&
- !slapi_filter_test_simple(post_e, memberof_group_filter))
+ memberof_rlock_config();
+ mainConfig = memberof_get_config();
+ if(pre_dn && post_dn &&
+ !slapi_filter_test_simple(post_e, mainConfig->group_filter))
+ {
+ interested = 1;
+ /* copy config so it doesn't change out from under us */
+ memberof_copy_config(&configCopy, mainConfig);
+ }
+ memberof_unlock_config();
+
+ if(interested)
{
Slapi_Attr *attr = 0;
@@ -475,15 +513,15 @@
/* get a list of member attributes present in the group
* entry that is being renamed. */
- if(0 == slapi_entry_attr_find(post_e, MEMBEROF_GROUP_ATTR, &attr))
+ if(0 == slapi_entry_attr_find(post_e, configCopy.groupattr, &attr))
{
- memberof_moddn_attr_list(pb, pre_dn, post_dn, attr);
+ memberof_moddn_attr_list(pb, &configCopy, pre_dn, post_dn, attr);
}
/* modrdn must change the dns in groups that have
* this group as a member.
*/
- memberof_replace_dn_from_groups(pb, pre_dn, post_dn);
+ memberof_replace_dn_from_groups(pb, &configCopy, pre_dn, post_dn);
memberof_unlock();
}
@@ -492,8 +530,7 @@
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
"<-- memberof_postop_modrdn\n" );
- return ret;slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
- "--> memberof_postop_modify\n" );
+ return ret;
}
typedef struct _replace_dn_data
@@ -503,11 +540,12 @@
char *type;
} replace_dn_data;
-int memberof_replace_dn_from_groups(Slapi_PBlock *pb, char *pre_dn, char *post_dn)
+int memberof_replace_dn_from_groups(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *pre_dn, char *post_dn)
{
- replace_dn_data data = {pre_dn, post_dn, MEMBEROF_GROUP_ATTR};
+ replace_dn_data data = {pre_dn, post_dn, config->groupattr};
- return memberof_call_foreach_dn(pb, pre_dn, MEMBEROF_GROUP_ATTR,
+ return memberof_call_foreach_dn(pb, pre_dn, config->groupattr,
memberof_replace_dn_type_callback, &data);
}
@@ -588,6 +626,10 @@
if(memberof_oktodo(pb) &&
(dn = memberof_getdn(pb)))
{
+ int config_copied = 0;
+ MemberOfConfig *mainConfig = 0;
+ MemberOfConfig configCopy = {0, 0, 0, 0};
+
/* get the mod set */
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
smods = slapi_mods_new();
@@ -597,10 +639,36 @@
smod = slapi_mods_get_first_smod(smods, next_mod);
while(smod)
{
+ int interested = 0;
char *type = (char *)slapi_mod_get_type(smod);
- /* we only care about the group attribute */
- if(slapi_attr_types_equivalent(type,MEMBEROF_GROUP_ATTR))
+ /* We only want to copy the config if we encounter an
+ * operation that we need to act on. We also want to
+ * only copy the config the first time it's needed so
+ * it remains the same for all mods in the operation,
+ * despite any config changes that may be made. */
+ if (!config_copied)
+ {
+ memberof_rlock_config();
+ mainConfig = memberof_get_config();
+
+ if(slapi_attr_types_equivalent(type, mainConfig->groupattr))
+ {
+ interested = 1;
+ /* copy config so it doesn't change out from under us */
+ memberof_copy_config(&configCopy, mainConfig);
+ config_copied = 1;
+ }
+
+ memberof_unlock_config();
+ } else {
+ if(slapi_attr_types_equivalent(type, configCopy.groupattr))
+ {
+ interested = 1;
+ }
+ }
+
+ if(interested)
{
int op = slapi_mod_get_operation(smod);
@@ -612,7 +680,7 @@
case LDAP_MOD_ADD:
{
/* add group DN to targets */
- memberof_add_smod_list(pb, dn, smod);
+ memberof_add_smod_list(pb, &configCopy, dn, smod);
break;
}
@@ -624,12 +692,12 @@
* entry, which the replace code deals with. */
if (slapi_mod_get_num_values(smod) == 0)
{
- memberof_replace_list(pb, dn);
+ memberof_replace_list(pb, &configCopy, dn);
}
else
{
/* remove group DN from target values in smod*/
- memberof_del_smod_list(pb, dn, smod);
+ memberof_del_smod_list(pb, &configCopy, dn, smod);
}
break;
}
@@ -637,7 +705,7 @@
case LDAP_MOD_REPLACE:
{
/* replace current values */
- memberof_replace_list(pb, dn);
+ memberof_replace_list(pb, &configCopy, dn);
break;
}
@@ -677,6 +745,7 @@
int memberof_postop_add(Slapi_PBlock *pb)
{
int ret = 0;
+ int interested = 0;
char *dn = 0;
slapi_log_error( SLAPI_LOG_TRACE, MEMBEROF_PLUGIN_SUBSYSTEM,
@@ -684,20 +753,33 @@
if(memberof_oktodo(pb) && (dn = memberof_getdn(pb)))
{
+ MemberOfConfig *mainConfig = 0;
+ MemberOfConfig configCopy = {0, 0, 0, 0};
struct slapi_entry *e = NULL;
slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &e );
+
/* is the entry of interest? */
- if(e && !slapi_filter_test_simple(e, memberof_group_filter))
+ memberof_rlock_config();
+ mainConfig = memberof_get_config();
+ if(e && !slapi_filter_test_simple(e, mainConfig->group_filter))
+ {
+ interested = 1;
+ /* copy config so it doesn't change out from under us */
+ memberof_copy_config(&configCopy, mainConfig);
+ }
+ memberof_unlock_config();
+
+ if(interested)
{
Slapi_Attr *attr = 0;
memberof_lock();
- if(0 == slapi_entry_attr_find(e, MEMBEROF_GROUP_ATTR, &attr))
+ if(0 == slapi_entry_attr_find(e, configCopy.groupattr, &attr))
{
- memberof_add_attr_list(pb, dn, attr);
+ memberof_add_attr_list(pb, &configCopy, dn, attr);
}
memberof_unlock();
@@ -774,9 +856,10 @@
*
* Also, we must not delete entries that are a member of the group
*/
-int memberof_modop_one(Slapi_PBlock *pb, int mod_op, char *op_this, char *op_to)
+int memberof_modop_one(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
+ char *op_this, char *op_to)
{
- return memberof_modop_one_r(pb, mod_op, op_this, op_this, op_to, 0);
+ return memberof_modop_one_r(pb, config, mod_op, op_this, op_this, op_to, 0);
}
/* memberof_modop_one_r()
@@ -784,19 +867,20 @@
* recursive function to perform above (most things don't need the replace arg)
*/
-int memberof_modop_one_r(Slapi_PBlock *pb, int mod_op, char *group_dn,
- char *op_this, char *op_to, memberofstringll *stack)
+int memberof_modop_one_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod_op,
+ char *group_dn, char *op_this, char *op_to, memberofstringll *stack)
{
return memberof_modop_one_replace_r(
- pb, mod_op, group_dn, op_this, 0, op_to, stack);
+ pb, config, mod_op, group_dn, op_this, 0, op_to, stack);
}
/* memberof_modop_one_replace_r()
*
* recursive function to perform above (with added replace arg)
*/
-int memberof_modop_one_replace_r(Slapi_PBlock *pb, int mod_op, char *group_dn,
- char *op_this, char *replace_with, char *op_to, memberofstringll *stack)
+int memberof_modop_one_replace_r(Slapi_PBlock *pb, MemberOfConfig *config,
+ int mod_op, char *group_dn, char *op_this, char *replace_with,
+ char *op_to, memberofstringll *stack)
{
int rc = 0;
LDAPMod mod;
@@ -805,7 +889,7 @@
char *val[2];
char *replace_val[2];
Slapi_PBlock *mod_pb = 0;
- char *attrlist[2] = {MEMBEROF_GROUP_ATTR,0};
+ char *attrlist[2] = {config->groupattr,0};
Slapi_DN *op_to_sdn = 0;
Slapi_Entry *e = 0;
memberofstringll *ll = 0;
@@ -813,7 +897,6 @@
Slapi_Value *to_dn_val = slapi_value_new_string(op_to);
Slapi_Value *this_dn_val = slapi_value_new_string(op_this);
-
/* determine if this is a group op or single entry */
op_to_sdn = slapi_sdn_new_dn_byref(op_to);
slapi_search_internal_get_entry( op_to_sdn, attrlist,
@@ -831,7 +914,7 @@
* membership given the delete operation that
* triggered this operation
*/
- memberof_test_membership(pb, group_dn);
+ memberof_test_membership(pb, config, group_dn);
}
goto bail;
@@ -855,10 +938,10 @@
}
slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_r: %s %s in %s\n"
+ "memberof_modop_one_replace_r: %s %s in %s\n"
,op_str, op_this, op_to);
- if(!slapi_filter_test_simple(e, memberof_group_filter))
+ if(!slapi_filter_test_simple(e, config->group_filter))
{
/* group */
Slapi_Value *ll_dn_val = 0;
@@ -871,7 +954,7 @@
{
ll_dn_val = slapi_value_new_string(ll->dn);
- if(0 == memberof_compare(&ll_dn_val, &to_dn_val))
+ if(0 == memberof_compare(config, &ll_dn_val, &to_dn_val))
{
slapi_value_free(&ll_dn_val);
@@ -879,7 +962,7 @@
recursive groups - bail out */
slapi_log_error( SLAPI_LOG_FATAL,
MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_r: group recursion"
+ "memberof_modop_one_replace_r: group recursion"
" detected in %s\n"
,op_to);
goto bail;
@@ -892,17 +975,17 @@
/* do op on group */
slapi_log_error( SLAPI_LOG_PLUGIN,
MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_r: descending into group %s\n",
+ "memberof_modop_one_replace_r: descending into group %s\n",
op_to);
/* Add the nested group's DN to the stack so we can detect loops later. */
ll = (memberofstringll*)slapi_ch_malloc(sizeof(memberofstringll));
ll->dn = op_to;
ll->next = stack;
- slapi_entry_attr_find( e, MEMBEROF_GROUP_ATTR, &members );
+ slapi_entry_attr_find( e, config->groupattr, &members );
if(members)
{
- memberof_mod_attr_list_r(pb, mod_op, group_dn, op_this, members, ll);
+ memberof_mod_attr_list_r(pb, config, mod_op, group_dn, op_this, members, ll);
}
{
@@ -921,11 +1004,11 @@
/* We want to avoid listing a group as a memberOf itself
* in case someone set up a circular grouping.
*/
- if (0 == memberof_compare(&this_dn_val, &to_dn_val))
+ if (0 == memberof_compare(config, &this_dn_val, &to_dn_val))
{
slapi_log_error( SLAPI_LOG_PLUGIN,
MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_r: not processing memberOf "
+ "memberof_modop_one_replace_r: not processing memberOf "
"operations on self entry: %s\n", this_dn_val);
goto bail;
}
@@ -935,13 +1018,13 @@
* it could still be a member in some other indirect manner. */
if(stack && LDAP_MOD_DELETE == mod_op)
{
- if(memberof_is_legit_member(pb, group_dn,
+ if(memberof_is_legit_member(pb, config, group_dn,
op_this, op_to, stack))
{
/* entry is member some other way too */
slapi_log_error( SLAPI_LOG_PLUGIN,
MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_r: not deleting %s\n"
+ "memberof_modop_one_replace_r: not deleting %s\n"
,op_to);
goto bail;
}
@@ -949,14 +1032,15 @@
/* Check if the entry is still an indirect member. If it is, we
* don't want to remove the memberOf value. */
- if((LDAP_MOD_DELETE != mod_op) || (0 == memberof_is_member(this_dn_val, to_dn_val))) {
+ if((LDAP_MOD_DELETE != mod_op) ||
+ (0 == memberof_is_member(config, this_dn_val, to_dn_val))) {
/* If we're about to add a memberOf value to an entry, we should first check
* if the value already exists. */
if((LDAP_MOD_ADD == mod_op) && (slapi_entry_attr_has_syntax_value(e,
- MEMBEROF_ATTR, this_dn_val)))
+ config->memberof_attr, this_dn_val)))
{
slapi_log_error( SLAPI_LOG_PLUGIN, MEMBEROF_PLUGIN_SUBSYSTEM,
- "memberof_modop_one_r: memberOf value %s already exists in "
+ "memberof_modop_one_replace_r: memberOf value %s already exists in "
"entry %s\n", op_this, op_to);
goto bail;
}
@@ -979,7 +1063,7 @@
val[1] = 0;
mod.mod_op = LDAP_MOD_REPLACE == mod_op?LDAP_MOD_DELETE:mod_op;
- mod.mod_type = MEMBEROF_ATTR;
+ mod.mod_type = config->memberof_attr;
mod.mod_values = val;
if(LDAP_MOD_REPLACE == mod_op)
@@ -988,7 +1072,7 @@
replace_val[1] = 0;
replace_mod.mod_op = LDAP_MOD_ADD;
- replace_mod.mod_type = MEMBEROF_ATTR;
+ replace_mod.mod_type = config->memberof_attr;
replace_mod.mod_values = replace_val;
}
@@ -1009,7 +1093,7 @@
if(LDAP_MOD_DELETE == mod_op)
{
/* fix up membership for groups that have been orphaned */
- memberof_test_membership_callback(e, 0);
+ memberof_test_membership_callback(e, config);
}
if(LDAP_MOD_ADD == mod_op)
@@ -1018,7 +1102,7 @@
* try to fix up membership for parent groups. */
if (rc == 0) {
/* fix up membership for groups that are now in scope */
- memberof_add_membership(pb, op_this, op_to);
+ memberof_add_membership(pb, config, op_this, op_to);
}
}
}
@@ -1037,9 +1121,9 @@
* Add addthis DN to the memberof attribute of addto
*
*/
-int memberof_add_one(Slapi_PBlock *pb, char *addthis, char *addto)
+int memberof_add_one(Slapi_PBlock *pb, MemberOfConfig *config, char *addthis, char *addto)
{
- return memberof_modop_one(pb, LDAP_MOD_ADD, addthis, addto);
+ return memberof_modop_one(pb, config, LDAP_MOD_ADD, addthis, addto);
}
/*
@@ -1048,9 +1132,9 @@
* Delete delthis DN from the memberof attribute of delfrom
*
*/
-int memberof_del_one(Slapi_PBlock *pb, char *delthis, char *delfrom)
+int memberof_del_one(Slapi_PBlock *pb, MemberOfConfig *config, char *delthis, char *delfrom)
{
- return memberof_modop_one(pb, LDAP_MOD_DELETE, delthis, delfrom);
+ return memberof_modop_one(pb, config, LDAP_MOD_DELETE, delthis, delfrom);
}
/*
@@ -1059,7 +1143,8 @@
* Perform mod for group DN to the memberof attribute of the list of targets
*
*/
-int memberof_mod_smod_list(Slapi_PBlock *pb, int mod, char *group_dn, Slapi_Mod *smod)
+int memberof_mod_smod_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
+ char *group_dn, Slapi_Mod *smod)
{
int rc = 0;
struct berval *bv = slapi_mod_get_first_value(smod);
@@ -1091,7 +1176,7 @@
strncpy(dn_str, bv->bv_val, (size_t)bv->bv_len);
- memberof_modop_one(pb, mod, group_dn, dn_str);
+ memberof_modop_one(pb, config, mod, group_dn, dn_str);
bv = slapi_mod_get_next_value(smod);
}
@@ -1108,9 +1193,10 @@
* Add group DN to the memberof attribute of the list of targets
*
*/
-int memberof_add_smod_list(Slapi_PBlock *pb, char *groupdn, Slapi_Mod *smod)
+int memberof_add_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *groupdn, Slapi_Mod *smod)
{
- return memberof_mod_smod_list(pb, LDAP_MOD_ADD, groupdn, smod);
+ return memberof_mod_smod_list(pb, config, LDAP_MOD_ADD, groupdn, smod);
}
@@ -1120,9 +1206,10 @@
* Remove group DN from the memberof attribute of the list of targets
*
*/
-int memberof_del_smod_list(Slapi_PBlock *pb, char *groupdn, Slapi_Mod *smod)
+int memberof_del_smod_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *groupdn, Slapi_Mod *smod)
{
- return memberof_mod_smod_list(pb, LDAP_MOD_DELETE, groupdn, smod);
+ return memberof_mod_smod_list(pb, config, LDAP_MOD_DELETE, groupdn, smod);
}
/**
@@ -1145,13 +1232,14 @@
* Perform mod for group DN to the memberof attribute of the list of targets
*
*/
-int memberof_mod_attr_list(Slapi_PBlock *pb, int mod, char *group_dn, Slapi_Attr *attr)
+int memberof_mod_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
+ char *group_dn, Slapi_Attr *attr)
{
- return memberof_mod_attr_list_r(pb, mod, group_dn, group_dn, attr, 0);
+ return memberof_mod_attr_list_r(pb, config, mod, group_dn, group_dn, attr, 0);
}
-int memberof_mod_attr_list_r(Slapi_PBlock *pb, int mod, char *group_dn, char *op_this,
- Slapi_Attr *attr, memberofstringll *stack)
+int memberof_mod_attr_list_r(Slapi_PBlock *pb, MemberOfConfig *config, int mod,
+ char *group_dn, char *op_this, Slapi_Attr *attr, memberofstringll *stack)
{
int rc = 0;
Slapi_Value *val = 0;
@@ -1189,12 +1277,12 @@
* to specify the new group DN value */
if(mod == LDAP_MOD_REPLACE)
{
- memberof_modop_one_replace_r(pb, mod, group_dn, op_this, group_dn,
+ memberof_modop_one_replace_r(pb, config, mod, group_dn, op_this, group_dn,
dn_str, stack);
}
else
{
- memberof_modop_one_r(pb, mod, group_dn, op_this, dn_str, stack);
+ memberof_modop_one_r(pb, config, mod, group_dn, op_this, dn_str, stack);
}
hint = slapi_attr_next_value(attr, hint, &val);
@@ -1212,9 +1300,10 @@
* Add group DN to the memberof attribute of the list of targets
*
*/
-int memberof_add_attr_list(Slapi_PBlock *pb, char *groupdn, Slapi_Attr *attr)
+int memberof_add_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, char *groupdn,
+ Slapi_Attr *attr)
{
- return memberof_mod_attr_list(pb, LDAP_MOD_ADD, groupdn, attr);
+ return memberof_mod_attr_list(pb, config, LDAP_MOD_ADD, groupdn, attr);
}
/*
@@ -1223,9 +1312,10 @@
* Remove group DN from the memberof attribute of the list of targets
*
*/
-int memberof_del_attr_list(Slapi_PBlock *pb, char *groupdn, Slapi_Attr *attr)
+int memberof_del_attr_list(Slapi_PBlock *pb, MemberOfConfig *config, char *groupdn,
+ Slapi_Attr *attr)
{
- return memberof_mod_attr_list(pb, LDAP_MOD_DELETE, groupdn, attr);
+ return memberof_mod_attr_list(pb, config, LDAP_MOD_DELETE, groupdn, attr);
}
/*
@@ -1234,7 +1324,8 @@
* Perform mod for group DN to the memberof attribute of the list of targets
*
*/
-int memberof_moddn_attr_list(Slapi_PBlock *pb, char *pre_dn, char *post_dn, Slapi_Attr *attr)
+int memberof_moddn_attr_list(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *pre_dn, char *post_dn, Slapi_Attr *attr)
{
int rc = 0;
Slapi_Value *val = 0;
@@ -1268,7 +1359,7 @@
strncpy(dn_str, bv->bv_val, (size_t)bv->bv_len);
- memberof_modop_one_replace_r(pb, LDAP_MOD_REPLACE,
+ memberof_modop_one_replace_r(pb, config, LDAP_MOD_REPLACE,
post_dn, pre_dn, post_dn, dn_str, 0);
hint = slapi_attr_next_value(attr, hint, &val);
@@ -1282,21 +1373,23 @@
typedef struct _memberof_add_groups
{
+ MemberOfConfig *config;
char *target_dn;
char *group_dn;
} memberof_add_groups;
-int memberof_add_membership(Slapi_PBlock *pb, char *op_this, char *op_to)
+int memberof_add_membership(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *op_this, char *op_to)
{
- memberof_add_groups data = {op_to, op_this};
+ memberof_add_groups data = {config, op_to, op_this};
- return memberof_call_foreach_dn(pb, op_this, MEMBEROF_GROUP_ATTR,
+ return memberof_call_foreach_dn(pb, op_this, config->groupattr,
memberof_add_groups_search_callback, &data);
}
int memberof_add_groups_search_callback(Slapi_Entry *e, void *callback_data)
{
- return memberof_add_one(0, slapi_entry_get_dn(e),
+ return memberof_add_one(0, ((memberof_add_groups*)callback_data)->config, slapi_entry_get_dn(e),
((memberof_add_groups*)callback_data)->target_dn);
}
@@ -1305,11 +1398,12 @@
* tests for direct membership of memberdn in group groupdn
* returns non-zero when true, zero otherwise
*/
-int memberof_is_direct_member(Slapi_Value *groupdn, Slapi_Value *memberdn)
+int memberof_is_direct_member(MemberOfConfig *config, Slapi_Value *groupdn,
+ Slapi_Value *memberdn)
{
int rc = 0;
Slapi_DN *sdn = 0;
- char *attrlist[2] = {MEMBEROF_GROUP_ATTR,0};
+ char *attrlist[2] = {config->groupattr,0};
Slapi_Entry *group_e = 0;
Slapi_Attr *attr = 0;
@@ -1320,7 +1414,7 @@
if(group_e)
{
- slapi_entry_attr_find(group_e, MEMBEROF_GROUP_ATTR, &attr );
+ slapi_entry_attr_find(group_e, config->groupattr, &attr );
if(attr)
{
rc = 0 == slapi_attr_value_find(
@@ -1339,19 +1433,20 @@
* will check for both direct and indirect membership.
* returns non-zero when true, zero otherwise
*/
-int memberof_is_member(Slapi_Value *groupdn, Slapi_Value *memberdn)
+int memberof_is_member(MemberOfConfig *config, Slapi_Value *groupdn,
+ Slapi_Value *memberdn)
{
memberofstringll *stack = 0;
/* Do a quick check to see if the entry is a direct
* member before tracing through nested groups. */
- if(memberof_is_direct_member(groupdn, memberdn))
+ if(memberof_is_direct_member(config, groupdn, memberdn))
{
/* entry is a direct member */
return 1;
}
- return memberof_is_member_r(groupdn, memberdn, stack);
+ return memberof_is_member_r(config, groupdn, memberdn, stack);
}
/* memberof_is_member_r()
@@ -1364,7 +1459,8 @@
*
* returns non-zero when true, zero otherwise
*/
-int memberof_is_member_r(Slapi_Value *groupdn, Slapi_Value *memberdn, memberofstringll *stack)
+int memberof_is_member_r(MemberOfConfig *config, Slapi_Value *groupdn,
+ Slapi_Value *memberdn, memberofstringll *stack)
{
Slapi_DN *member_sdn = 0;
Slapi_DN *base_sdn = 0;
@@ -1382,7 +1478,7 @@
{
ll_dn_val = slapi_value_new_string(ll->dn);
- if(0 == memberof_compare(&ll_dn_val, &memberdn))
+ if(0 == memberof_compare(config, &ll_dn_val, &memberdn))
{
slapi_value_free(&ll_dn_val);
@@ -1393,6 +1489,11 @@
"memberof_is_member_r: group recursion"
" detected in %s\n"
,slapi_value_get_string(memberdn));
+ /* We set this to null to avoid freeing it twice.
+ * If we don't do this, we'd free ll in the bail section
+ * and the caller (ourselves since we're using recursion)
+ * would free it as well. */
+ ll = 0;
goto bail;
}
@@ -1419,11 +1520,8 @@
* and keep looping until we've exhausted it. */
if(base_sdn)
{
- int filter_size =
- (strlen(MEMBEROF_GROUP_ATTR) +
- strlen(slapi_value_get_string(memberdn)) + 4); /* 4 for (=) + null */
- filter_str = (char*)slapi_ch_malloc(filter_size);
- sprintf(filter_str, "(%s=%s)", MEMBEROF_GROUP_ATTR, slapi_value_get_string(memberdn));
+ filter_str = slapi_ch_smprintf("(%s=%s)", config->groupattr,
+ slapi_value_get_string(memberdn));
}
if(filter_str)
@@ -1465,7 +1563,7 @@
* see if any of them are the group we are trying to find.
* We do this by doing a recursive call on this function. */
Slapi_Value *entrydn = slapi_value_new_string(slapi_entry_get_ndn(entries[i]));
- rc = memberof_is_member_r(groupdn, entrydn, ll);
+ rc = memberof_is_member_r(config, groupdn, entrydn, ll);
slapi_value_free(&entrydn);
}
}
@@ -1498,10 +1596,10 @@
* iterate until a pass fails to move a group over to member groups
* remaining groups should be deleted
*/
-int memberof_test_membership(Slapi_PBlock *pb, char *group_dn)
+int memberof_test_membership(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn)
{
- return memberof_call_foreach_dn(pb, group_dn, MEMBEROF_ATTR,
- memberof_test_membership_callback ,0);
+ return memberof_call_foreach_dn(pb, group_dn, config->memberof_attr,
+ memberof_test_membership_callback , config);
}
/*
@@ -1519,6 +1617,7 @@
Slapi_Value **member_array = 0;
Slapi_Value **candidate_array = 0;
Slapi_Value *entry_dn = 0;
+ MemberOfConfig *config = (MemberOfConfig *)callback_data;
entry_dn = slapi_value_new_string(slapi_entry_get_dn(e));
@@ -1528,7 +1627,7 @@
}
/* divide groups into member and non-member lists */
- slapi_entry_attr_find(e, MEMBEROF_ATTR, &attr );
+ slapi_entry_attr_find(e, config->memberof_attr, &attr );
if(attr)
{
slapi_attr_get_numvalues( attr, &total);
@@ -1555,7 +1654,7 @@
while(val)
{
/* test for direct membership */
- if(memberof_is_direct_member(val, entry_dn))
+ if(memberof_is_direct_member(config, val, entry_dn))
{
/* it is a member */
member_array[m_index] = val;
@@ -1602,6 +1701,7 @@
}
if(memberof_is_direct_member(
+ config,
candidate_array[inner_index],
member_array[outer_index]))
{
@@ -1640,7 +1740,7 @@
}
memberof_del_one(
- 0,
+ 0, config,
(char*)slapi_value_get_string(
candidate_array[outer_index]),
(char*)slapi_value_get_string(entry_dn));
@@ -1675,7 +1775,7 @@
* Perform replace the group DN list in the memberof attribute of the list of targets
*
*/
-int memberof_replace_list(Slapi_PBlock *pb, char *group_dn)
+int memberof_replace_list(Slapi_PBlock *pb, MemberOfConfig *config, char *group_dn)
{
struct slapi_entry *pre_e = NULL;
struct slapi_entry *post_e = NULL;
@@ -1687,8 +1787,8 @@
if(pre_e && post_e)
{
- slapi_entry_attr_find( pre_e, MEMBEROF_GROUP_ATTR, &pre_attr );
- slapi_entry_attr_find( post_e, MEMBEROF_GROUP_ATTR, &post_attr );
+ slapi_entry_attr_find( pre_e, config->groupattr, &pre_attr );
+ slapi_entry_attr_find( post_e, config->groupattr, &post_attr );
}
if(pre_attr || post_attr)
@@ -1711,6 +1811,14 @@
slapi_attr_get_numvalues( post_attr, &post_total);
}
+ /* Stash a plugin global pointer here and have memberof_qsort_compare
+ * use it. We have to do this because we use memberof_qsort_compare
+ * as the comparator function for qsort, which requires the function
+ * to only take two void* args. This is thread-safe since we only
+ * store and use the pointer while holding the memberOf operation
+ * lock. */
+ qsortConfig = config;
+
if(pre_total)
{
pre_array =
@@ -1721,7 +1829,7 @@
pre_array,
pre_total,
sizeof(Slapi_Value*),
- memberof_compare);
+ memberof_qsort_compare);
}
if(post_total)
@@ -1734,9 +1842,11 @@
post_array,
post_total,
sizeof(Slapi_Value*),
- memberof_compare);
+ memberof_qsort_compare);
}
+ qsortConfig = 0;
+
/* work through arrays, following these rules:
in pre, in post, do nothing
@@ -1749,7 +1859,7 @@
{
/* add the rest of post */
memberof_add_one(
- pb,
+ pb, config,
group_dn,
(char*)slapi_value_get_string(
post_array[post_index]));
@@ -1760,7 +1870,7 @@
{
/* delete the rest of pre */
memberof_del_one(
- pb,
+ pb, config,
group_dn,
(char*)slapi_value_get_string(
pre_array[pre_index]));
@@ -1771,6 +1881,7 @@
{
/* decide what to do */
int cmp = memberof_compare(
+ config,
&(pre_array[pre_index]),
&(post_array[post_index]));
@@ -1778,7 +1889,7 @@
{
/* delete pre array */
memberof_del_one(
- pb,
+ pb, config,
group_dn,
(char*)slapi_value_get_string(
pre_array[pre_index]));
@@ -1789,7 +1900,7 @@
{
/* add post array */
memberof_add_one(
- pb,
+ pb, config,
group_dn,
(char*)slapi_value_get_string(
post_array[post_index]));
@@ -1832,42 +1943,35 @@
*
* compare two attr values
*/
-int memberof_compare(const void *a, const void *b)
+int memberof_compare(MemberOfConfig *config, const void *a, const void *b)
{
- static Slapi_Attr *attr = 0;
- static int first_time = 1;
Slapi_Value *val1 = *((Slapi_Value **)a);
Slapi_Value *val2 = *((Slapi_Value **)b);
- if(first_time)
- {
- first_time = 0;
- attr = slapi_attr_new();
- slapi_attr_init(attr, MEMBEROF_GROUP_ATTR);
- }
-
return slapi_attr_value_cmp(
- attr,
- slapi_value_get_berval(val1),
+ config->group_slapiattr,
+ slapi_value_get_berval(val1),
slapi_value_get_berval(val2));
}
-/* memberof_string2filter()
+/* memberof_qsort_compare()
*
- * For some reason slapi_str2filter writes to its input
- * which means you cannot pass in a string constant
- * so this is a fix up function for that
+ * This is a version of memberof_compare that uses a plugin
+ * global copy of the config. We'd prefer to pass in a copy
+ * of config that is local to the running thread, but we can't
+ * do this since qsort is using us as a comparator function.
+ * We should only use this function when using qsort, and only
+ * when the memberOf lock is acquired.
*/
-Slapi_Filter *memberof_string2filter(char *strfilter)
+int memberof_qsort_compare(const void *a, const void *b)
{
- Slapi_Filter *ret = 0;
- char *idontbelieveit = slapi_ch_strdup(strfilter);
-
- ret = slapi_str2filter( idontbelieveit );
-
- slapi_ch_free_string(&idontbelieveit);
+ Slapi_Value *val1 = *((Slapi_Value **)a);
+ Slapi_Value *val2 = *((Slapi_Value **)b);
- return ret;
+ return slapi_attr_value_cmp(
+ qsortConfig->group_slapiattr,
+ slapi_value_get_berval(val1),
+ slapi_value_get_berval(val2));
}
/* memberof_is_legit_member()
@@ -1880,8 +1984,8 @@
* the second from bottom one of our stack do not appear
* in the membership attribute of the group
*/
-int memberof_is_legit_member(Slapi_PBlock *pb, char *group_dn,
- char *op_this, char *op_to, memberofstringll *stack)
+int memberof_is_legit_member(Slapi_PBlock *pb, MemberOfConfig *config,
+ char *group_dn, char *op_this, char *op_to, memberofstringll *stack)
{
int rc = 0;
Slapi_DN *group_sdn = 0;
@@ -1890,10 +1994,9 @@
Slapi_Entry *opto_e = 0;
char *filter_str = 0;
Slapi_Filter *filter = 0;
- int filter_size = 0;
memberofstringll *ll = 0;
- char *attrlist[2] = {MEMBEROF_GROUP_ATTR,0};
- char *optolist[2] = {MEMBEROF_ATTR,0};
+ char *attrlist[2] = {config->groupattr,0};
+ char *optolist[2] = {config->memberof_attr,0};
Slapi_Attr *memberof = 0;
Slapi_Value *memberdn = 0;
int hint = 0;
@@ -1913,14 +2016,8 @@
goto bail;
}
- filter_size = 2 *
- (strlen(MEMBEROF_GROUP_ATTR) +
- strlen(op_to) + 4); /* 4 for (=) + null */
- filter_str = (char*)slapi_ch_malloc(filter_size);
-
- sprintf(filter_str, "(%s=%s)", MEMBEROF_GROUP_ATTR, op_to);
-
- filter = memberof_string2filter(filter_str);
+ filter_str = slapi_ch_smprintf("(%s=%s)", config->groupattr, op_to);
+ filter = slapi_str2filter(filter_str);
if(!slapi_filter_test_simple(group_e, filter))
{
@@ -1966,7 +2063,7 @@
if(opto_e)
{
- slapi_entry_attr_find(opto_e, MEMBEROF_ATTR, &memberof);
+ slapi_entry_attr_find(opto_e, config->memberof_attr, &memberof);
}
if(0 == memberof)
@@ -1981,7 +2078,7 @@
{
char *dn = (char*)slapi_value_get_string(memberdn);
int current_size =
- (strlen(MEMBEROF_GROUP_ATTR) +
+ (strlen(config->groupattr) +
strlen(dn) + 4); /* 4 for (=) + null */
/* disregard the group being removed */
@@ -1991,15 +2088,14 @@
continue;
}
- if(current_size > filter_size)
+ if (current_size > strlen(filter_str))
{
- filter_size = 2 * current_size;
- filter_str = slapi_ch_realloc(
- filter_str, filter_size);
+ int filter_size = 2 * current_size;
+ filter_str = slapi_ch_realloc(filter_str, filter_size);
}
- sprintf(filter_str, "(%s=%s)", MEMBEROF_GROUP_ATTR, dn);
- filter = memberof_string2filter(filter_str);
+ sprintf(filter_str, "(%s=%s)", config->groupattr, dn);
+ filter = slapi_str2filter(filter_str);
if(!slapi_filter_test_simple(group_e, filter))
{
@@ -2046,6 +2142,7 @@
void memberof_fixup_task_thread(void *arg)
{
+ MemberOfConfig configCopy = {0, 0, 0, 0};
Slapi_Task *task = (Slapi_Task *)arg;
task_data *td = NULL;
int rc = 0;
@@ -2057,8 +2154,22 @@
slapi_task_log_notice(task, "Memberof task starts (arg: %s) ...\n",
td->filter_str);
+ /* We need to get the config lock first. Trying to get the
+ * config lock after we already hold the op lock can cause
+ * a deadlock. */
+ memberof_rlock_config();
+ /* copy config so it doesn't change out from under us */
+ memberof_copy_config(&configCopy, memberof_get_config());
+ memberof_unlock_config();
+
+ /* get the memberOf operation lock */
+ memberof_lock();
+
/* do real work */
- rc = memberof_fix_memberof(td->dn, td->filter_str);
+ rc = memberof_fix_memberof(&configCopy, td->dn, td->filter_str);
+
+ /* release the memberOf operation lock */
+ memberof_unlock();
slapi_task_log_notice(task, "Memberof task finished.");
slapi_task_log_status(task, "Memberof task finished.");
@@ -2164,7 +2275,7 @@
}
}
-int memberof_fix_memberof(char *dn, char *filter_str)
+int memberof_fix_memberof(MemberOfConfig *config, char *dn, char *filter_str)
{
int rc = 0;
Slapi_PBlock *search_pb = slapi_pblock_new();
@@ -2176,7 +2287,7 @@
0);
rc = slapi_search_internal_callback_pb(search_pb,
- 0,
+ config,
0, memberof_fix_memberof_callback,
0);
@@ -2196,13 +2307,14 @@
{
int rc = 0;
char *dn = slapi_entry_get_dn(e);
- memberof_add_groups data = {dn, dn};
+ MemberOfConfig *config = (MemberOfConfig *)callback_data;
+ memberof_add_groups data = {config, dn, dn};
/* step 1 */
- slapi_entry_attr_delete(e, MEMBEROF_ATTR);
+ slapi_entry_attr_delete(e, config->memberof_attr);
/* step 2 and 3 */
- rc = memberof_call_foreach_dn(0, dn, MEMBEROF_GROUP_ATTR,
+ rc = memberof_call_foreach_dn(0, dn, config->groupattr,
memberof_add_groups_search_callback, &data);
return rc;
More information about the Fedora-directory-commits
mailing list