瀏覽代碼

Resolves: 450989
Summary: Make memberOf plug-in attributes configurable.

Nathan Kinder 17 年之前
父節點
當前提交
0895c26fcf

+ 2 - 1
Makefile.am

@@ -651,7 +651,8 @@ libcollation_plugin_la_LINK = $(CXXLINK)
 #------------------------
 # libmemberof-plugin
 #------------------------
-libmemberof_plugin_la_SOURCES= ldap/servers/plugins/memberof/memberof.c
+libmemberof_plugin_la_SOURCES= ldap/servers/plugins/memberof/memberof.c \
+	ldap/servers/plugins/memberof/memberof_config.c
 
 libmemberof_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
 libmemberof_plugin_la_LDFLAGS = -avoid-version

+ 18 - 2
Makefile.in

@@ -276,7 +276,8 @@ libhttp_client_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(libhttp_client_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
 libmemberof_plugin_la_LIBADD =
-am_libmemberof_plugin_la_OBJECTS = ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.lo
+am_libmemberof_plugin_la_OBJECTS = ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.lo \
+	ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo
 libmemberof_plugin_la_OBJECTS = $(am_libmemberof_plugin_la_OBJECTS)
 libmemberof_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -1620,7 +1621,9 @@ libcollation_plugin_la_LINK = $(CXXLINK)
 #------------------------
 # libmemberof-plugin
 #------------------------
-libmemberof_plugin_la_SOURCES = ldap/servers/plugins/memberof/memberof.c
+libmemberof_plugin_la_SOURCES = ldap/servers/plugins/memberof/memberof.c \
+	ldap/servers/plugins/memberof/memberof_config.c
+
 libmemberof_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
 libmemberof_plugin_la_LDFLAGS = -avoid-version
 
@@ -2668,6 +2671,9 @@ ldap/servers/plugins/memberof/$(DEPDIR)/$(am__dirstamp):
 ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.lo:  \
 	ldap/servers/plugins/memberof/$(am__dirstamp) \
 	ldap/servers/plugins/memberof/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo:  \
+	ldap/servers/plugins/memberof/$(am__dirstamp) \
+	ldap/servers/plugins/memberof/$(DEPDIR)/$(am__dirstamp)
 libmemberof-plugin.la: $(libmemberof_plugin_la_OBJECTS) $(libmemberof_plugin_la_DEPENDENCIES) 
 	$(libmemberof_plugin_la_LINK) -rpath $(serverplugindir) $(libmemberof_plugin_la_OBJECTS) $(libmemberof_plugin_la_LIBADD) $(LIBS)
 lib/libaccess/$(am__dirstamp):
@@ -4041,6 +4047,8 @@ mostlyclean-compile:
 	-rm -f ldap/servers/plugins/http/libhttp_client_plugin_la-http_impl.lo
 	-rm -f ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.$(OBJEXT)
 	-rm -f ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.lo
+	-rm -f ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.$(OBJEXT)
+	-rm -f ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo
 	-rm -f ldap/servers/plugins/pam_passthru/libpam_passthru_plugin_la-pam_ptconfig.$(OBJEXT)
 	-rm -f ldap/servers/plugins/pam_passthru/libpam_passthru_plugin_la-pam_ptconfig.lo
 	-rm -f ldap/servers/plugins/pam_passthru/libpam_passthru_plugin_la-pam_ptdebug.$(OBJEXT)
@@ -4781,6 +4789,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/http/$(DEPDIR)/libhttp_client_plugin_la-http_client.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/http/$(DEPDIR)/libhttp_client_plugin_la-http_impl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/memberof/$(DEPDIR)/libmemberof_plugin_la-memberof.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/memberof/$(DEPDIR)/libmemberof_plugin_la-memberof_config.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pam_passthru/$(DEPDIR)/libpam_passthru_plugin_la-pam_ptconfig.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pam_passthru/$(DEPDIR)/libpam_passthru_plugin_la-pam_ptdebug.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/pam_passthru/$(DEPDIR)/libpam_passthru_plugin_la-pam_ptimpl.Plo@am__quote@
@@ -6096,6 +6105,13 @@ ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.lo: ldap/servers/pl
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmemberof_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof.lo `test -f 'ldap/servers/plugins/memberof/memberof.c' || echo '$(srcdir)/'`ldap/servers/plugins/memberof/memberof.c
 
+ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo: ldap/servers/plugins/memberof/memberof_config.c
+@am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmemberof_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo -MD -MP -MF ldap/servers/plugins/memberof/$(DEPDIR)/libmemberof_plugin_la-memberof_config.Tpo -c -o ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo `test -f 'ldap/servers/plugins/memberof/memberof_config.c' || echo '$(srcdir)/'`ldap/servers/plugins/memberof/memberof_config.c
+@am__fastdepCC_TRUE@	mv -f ldap/servers/plugins/memberof/$(DEPDIR)/libmemberof_plugin_la-memberof_config.Tpo ldap/servers/plugins/memberof/$(DEPDIR)/libmemberof_plugin_la-memberof_config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='ldap/servers/plugins/memberof/memberof_config.c' object='ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmemberof_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/memberof/libmemberof_plugin_la-memberof_config.lo `test -f 'ldap/servers/plugins/memberof/memberof_config.c' || echo '$(srcdir)/'`ldap/servers/plugins/memberof/memberof_config.c
+
 lib/libadmin/libns_dshttpd_la-error.lo: lib/libadmin/error.c
 @am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libns_dshttpd_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib/libadmin/libns_dshttpd_la-error.lo -MD -MP -MF lib/libadmin/$(DEPDIR)/libns_dshttpd_la-error.Tpo -c -o lib/libadmin/libns_dshttpd_la-error.lo `test -f 'lib/libadmin/error.c' || echo '$(srcdir)/'`lib/libadmin/error.c
 @am__fastdepCC_TRUE@	mv -f lib/libadmin/$(DEPDIR)/libns_dshttpd_la-error.Tpo lib/libadmin/$(DEPDIR)/libns_dshttpd_la-error.Plo

+ 2 - 0
ldap/ldif/template-dse.ldif.in

@@ -408,6 +408,8 @@ nsslapd-plugininitfunc: memberof_postop_init
 nsslapd-plugintype: postoperation
 nsslapd-pluginenabled: off
 nsslapd-plugin-depends-on-type: database
+memberOfGroupAttr: member
+memberOfAttr: memberOf
 
 dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config
 objectclass: top

File diff suppressed because it is too large
+ 262 - 154
ldap/servers/plugins/memberof/memberof.c


+ 95 - 0
ldap/servers/plugins/memberof/memberof.h

@@ -0,0 +1,95 @@
+/** 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_ */

+ 341 - 0
ldap/servers/plugins/memberof/memberof_config.c

@@ -0,0 +1,341 @@
+/** 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);
+}

Some files were not shown because too many files changed in this diff