[Fedora-directory-commits] ldapserver/ldap/servers/plugins/memberof memberof.c, NONE, 1.1
Nathan Kinder (nkinder)
fedora-directory-commits at redhat.com
Tue Feb 19 06:04:58 UTC 2008
- Previous message (by thread): [Fedora-directory-commits] ldapserver/ldap/servers/plugins/memberof - New directory
- Next message (by thread): [Fedora-directory-commits] ldapserver Makefile.am, 1.64, 1.65 Makefile.in, 1.82, 1.83 aclocal.m4, 1.61, 1.62 config.guess, 1.45, 1.46 config.h.in, 1.12, 1.13 config.sub, 1.45, 1.46 configure, 1.78, 1.79 depcomp, 1.46, 1.47 install-sh, 1.46, 1.47 ltmain.sh, 1.23, 1.24 missing, 1.46, 1.47
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: nkinder
Update of /cvs/dirsec/ldapserver/ldap/servers/plugins/memberof
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv13952/ldap/servers/plugins/memberof
Added Files:
memberof.c
Log Message:
Initial import of memberof plugin from FreeIPA (refactored from changeset 640:9c57bd91b32f if ipa-memberof.c).
--- NEW FILE memberof.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.
*
* Authors:
* Pete Rowley <prowley at redhat.com>
*
* Copyright (C) 2007 Red Hat, Inc.
* All rights reserved.
* END COPYRIGHT BLOCK
**/
/* The memberof plugin updates the memberof attribute of entries
* based on modifications performed on groupofuniquenames entries
*
* In addition the plugin provides a DS task that may be started
* administrative clients and that creates the initial memberof
* list for imported entries and/or fixes the memberof list of
* existing entries that have inconsistent state (for example,
* if the memberof attribute was incorrectly edited directly)
*
* To start the memberof task add an entry like:
*
* dn: cn=memberof task 2, cn=memberof task, cn=tasks, cn=config
* objectClass: top
* objectClass: extensibleObject
* cn: sample task
* basedn: dc=example, dc=com
* filter: (uid=test4)
*
* where "basedn" is required and refers to the top most node to perform the
* task on, and where "filter" is an optional attribute that provides a filter
* describing the entries to be worked on
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "slapi-plugin.h"
#include "dirver.h"
#include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
#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_ATTR_TYPE "uid"
#define MEMBEROF_GROUP_FILTER "(" MEMBEROF_GROUP_ATTR "=*)"
#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;
typedef struct _memberofstringll
{
char *dn;
void *next;
} memberofstringll;
/****** secrets *********/
/*from FDS slap.h
* until we get a proper api for access
*/
#define TASK_RUNNING_AS_TASK 0x0
/*from FDS slapi-private.h
* until we get a proper api for access
*/
#define SLAPI_DSE_CALLBACK_OK (1)
#define SLAPI_DSE_CALLBACK_ERROR (-1)
#define SLAPI_DSE_CALLBACK_DO_NOT_APPLY (0)
/******************************************************************************
* Online tasks interface (to support import, export, etc)
* After some cleanup, we could consider making these public.
*/
struct _slapi_task {
struct _slapi_task *next;
char *task_dn;
int task_exitcode; /* for the end user */
int task_state; /* (see above) */
int task_progress; /* number between 0 and task_work */
int task_work; /* "units" of work to be done */
int task_flags; /* (see above) */
/* it is the task's responsibility to allocate this memory & free it: */
char *task_status; /* transient status info */
char *task_log; /* appended warnings, etc */
void *task_private; /* for use by backends */
TaskCallbackFn cancel; /* task has been cancelled by user */
TaskCallbackFn destructor; /* task entry is being destroyed */
int task_refcount;
};
/****** secrets ********/
/*** function prototypes ***/
/* exported functions */
int memberof_postop_init(Slapi_PBlock *pb );
/* plugin callbacks */
static int memberof_postop_del(Slapi_PBlock *pb );
static int memberof_postop_modrdn(Slapi_PBlock *pb );
static int memberof_postop_modify(Slapi_PBlock *pb );
static int memberof_postop_add(Slapi_PBlock *pb );
static int memberof_postop_start(Slapi_PBlock *pb);
static int memberof_postop_close(Slapi_PBlock *pb);
/* 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 memberofd_replace_list(Slapi_PBlock *pb, 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 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_call_foreach_dn(Slapi_PBlock *pb, char *dn,
char *type, plugin_search_entry_callback callback, void *callback_data);
static int memberof_is_group_member(Slapi_Value *groupdn, Slapi_Value *memberdn);
static int memberof_test_membership(Slapi_PBlock *pb, char *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_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_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
Slapi_Entry *eAfter, int *returncode, char *returntext,
void *arg);
static const char *fetch_attr(Slapi_Entry *e, const char *attrname,
const char *default_val);
[...1631 lines suppressed...]
"<-- memberof_is_legit_member\n" );
return rc;
}
void memberof_lock()
{
slapi_lock_mutex(memberof_operation_lock);
}
void memberof_unlock()
{
slapi_unlock_mutex(memberof_operation_lock);
}
/*
*
*/
typedef struct _task_data
{
char *dn;
char *filter_str;
Slapi_Task *task;
} task_data;
void memberof_memberof_fixup_task_thread(void *arg)
{
task_data *td = (task_data *)arg;
Slapi_Task *task = td->task;
int rc = 0;
task->task_work = 1;
task->task_progress = 0;
task->task_state = SLAPI_TASK_RUNNING;
slapi_task_status_changed(task);
slapi_task_log_notice(task, "Memberof task starts (arg: %s) ...\n",
td->filter_str);
/* do real work */
rc = memberof_fix_memberof(td->dn, td->filter_str);
slapi_task_log_notice(task, "Memberof task finished.");
slapi_task_log_status(task, "Memberof task finished.");
task->task_progress = 1;
task->task_exitcode = rc;
task->task_state = SLAPI_TASK_FINISHED;
slapi_task_status_changed(task);
slapi_ch_free_string(&td->dn);
slapi_ch_free_string(&td->filter_str);
{
/* make the compiler happy */
void *ptd = td;
slapi_ch_free(&ptd);
}
}
/* extract a single value from the entry (as a string) -- if it's not in the
* entry, the default will be returned (which can be NULL).
* you do not need to free anything returned by this.
*/
const char *fetch_attr(Slapi_Entry *e, const char *attrname,
const char *default_val)
{
Slapi_Attr *attr;
Slapi_Value *val = NULL;
if (slapi_entry_attr_find(e, attrname, &attr) != 0)
return default_val;
slapi_attr_first_value(attr, &val);
return slapi_value_get_string(val);
}
int memberof_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
Slapi_Entry *eAfter, int *returncode, char *returntext,
void *arg)
{
PRThread *thread = NULL;
int rv = SLAPI_DSE_CALLBACK_OK;
task_data *mytaskdata = NULL;
Slapi_Task *task = NULL;
const char *filter;
const char *dn = 0;
*returncode = LDAP_SUCCESS;
/* get arg(s) */
if ((dn = fetch_attr(e, "basedn", 0)) == NULL)
{
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
rv = SLAPI_DSE_CALLBACK_ERROR;
goto out;
}
if ((filter = fetch_attr(e, "filter", "(objectclass=inetuser)")) == NULL)
{
*returncode = LDAP_OBJECT_CLASS_VIOLATION;
rv = SLAPI_DSE_CALLBACK_ERROR;
goto out;
}
/* allocate new task now */
task = slapi_new_task(slapi_entry_get_ndn(e));
task->task_state = SLAPI_TASK_SETUP;
task->task_work = 1;
task->task_progress = 0;
/* create a pblock to pass the necessary info to the task thread */
mytaskdata = (task_data*)slapi_ch_malloc(sizeof(task_data));
if (mytaskdata == NULL)
{
*returncode = LDAP_OPERATIONS_ERROR;
rv = SLAPI_DSE_CALLBACK_ERROR;
goto out;
}
mytaskdata->dn = slapi_ch_strdup(dn);
mytaskdata->filter_str = slapi_ch_strdup(filter);
mytaskdata->task = task;
/* start the sample task as a separate thread */
thread = PR_CreateThread(PR_USER_THREAD, memberof_memberof_fixup_task_thread,
(void *)mytaskdata, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
if (thread == NULL)
{
slapi_log_error( SLAPI_LOG_FATAL, MEMBEROF_PLUGIN_SUBSYSTEM,
"unable to create task thread!\n");
*returncode = LDAP_OPERATIONS_ERROR;
rv = SLAPI_DSE_CALLBACK_ERROR;
slapi_ch_free_string(&mytaskdata->dn);
slapi_ch_free_string(&mytaskdata->filter_str);
{
void *ptask = mytaskdata;
slapi_ch_free(&ptask);
goto out;
}
}
/* thread successful -- don't free the pb, let the thread do that. */
return SLAPI_DSE_CALLBACK_OK;
out:
if (task)
{
slapi_destroy_task(task);
}
return rv;
}
int memberof_fix_memberof(char *dn, char *filter_str)
{
int rc = 0;
Slapi_PBlock *search_pb = slapi_pblock_new();
slapi_search_internal_set_pb(search_pb, dn,
LDAP_SCOPE_SUBTREE, filter_str, 0, 0,
0, 0,
memberof_get_plugin_id(),
0);
rc = slapi_search_internal_callback_pb(search_pb,
0,
0, memberof_fix_memberof_callback,
0);
slapi_pblock_destroy(search_pb);
return rc;
}
/* memberof_fix_memberof_callback()
* Add initial and/or fix up broken group list in entry
*
* 1. Make sure direct membership groups are in the entry
* 2. Add all groups that current group list allows through nested membership
* 3. Trim groups that have no relationship to entry
*/
int memberof_fix_memberof_callback(Slapi_Entry *e, void *callback_data)
{
int rc = 0;
char *dn = slapi_entry_get_dn(e);
memberof_add_groups data = {dn, dn};
/* step 1. and step 2. */
rc = memberof_call_foreach_dn(0, dn, MEMBEROF_GROUP_ATTR,
memberof_add_groups_search_callback, &data);
if(0 == rc)
{
/* step 3. */
rc = memberof_test_membership_callback(e, 0);
}
return rc;
}
- Previous message (by thread): [Fedora-directory-commits] ldapserver/ldap/servers/plugins/memberof - New directory
- Next message (by thread): [Fedora-directory-commits] ldapserver Makefile.am, 1.64, 1.65 Makefile.in, 1.82, 1.83 aclocal.m4, 1.61, 1.62 config.guess, 1.45, 1.46 config.h.in, 1.12, 1.13 config.sub, 1.45, 1.46 configure, 1.78, 1.79 depcomp, 1.46, 1.47 install-sh, 1.46, 1.47 ltmain.sh, 1.23, 1.24 missing, 1.46, 1.47
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Fedora-directory-commits
mailing list