| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113 |
- /** 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) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include "portable.h"
- #include "slapi-plugin.h"
- #include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
- #include "dirver.h"
-
- /* This is naughty ... */
- #include "slapi-private.h"
-
- /* include NSPR header files */
- #include "slap.h"
- #include "prthread.h"
- #include "prlock.h"
- #include "prerror.h"
- #include "prcvar.h"
- #include "prio.h"
- #include "avl.h"
- #include "vattr_spi.h"
- #include "roles_cache.h"
- #include "views.h"
- #ifdef SOLARIS
- #include <tnf/probe.h>
- #else
- #define TNF_PROBE_0(a,b,c)
- #endif
- #define MAX_NESTED_ROLES 30
- static char *allUserAttributes[] = {
- LDAP_ALL_USER_ATTRS,
- NULL
- };
- /* views scoping */
- static void **views_api;
- /* Service provider handler */
- static vattr_sp_handle *vattr_handle = NULL;
- /* List of nested roles */
- typedef struct _role_object_nested {
- Slapi_DN *dn; /* value of attribute nsroledn in a nested role definition */
- } role_object_nested;
- /* Role object structure */
- typedef struct _role_object {
- Slapi_DN *dn; /* dn of a role entry */
- int type; /* ROLE_TYPE_MANAGED|ROLE_TYPE_FILTERED|ROLE_TYPE_NESTED */
- Slapi_Filter *filter; /* if ROLE_TYPE_FILTERED */
- Avlnode *avl_tree; /* if ROLE_TYPE_NESTED: tree of nested DNs (avl_data is a role_object_nested struct) */
- } role_object;
- /* Structure containing the roles definitions for a given suffix */
- typedef struct _roles_cache_def {
- /* Suffix DN*/
- Slapi_DN *suffix_dn;
- /* Module level thread control */
- PRThread *roles_tid;
- int keeprunning;
- PRRWLock *cache_lock;
- Slapi_Mutex *stop_lock;
- Slapi_Mutex *change_lock;
- Slapi_CondVar *something_changed;
- Slapi_Mutex *create_lock;
- Slapi_CondVar *suffix_created;
- int is_ready;
- /* Root of the avl tree containing all the roles definitions
- NB: avl_data field is of type role_object
- */
- Avlnode *avl_tree;
- /* Next roles suffix definitions */
- struct _roles_cache_def *next;
- /* Info passed from the server when an notification is sent to the plugin */
- char *notified_dn;
- Slapi_Entry *notified_entry;
- int notified_operation;
- } roles_cache_def;
- /* Global list containing all the roles definitions per suffix */
- static roles_cache_def *roles_list = NULL;
- static PRRWLock *global_lock = NULL;
- /* Structure holding the nsrole values */
- typedef struct _roles_cache_build_result
- {
- Slapi_ValueSet **nsrole_values; /* nsrole computed values */
- Slapi_Entry *requested_entry; /* entry to get nsrole from */
- int has_value; /* flag to determine if a new value has been added to the result */
- int need_value; /* flag to determine if we need the result */
- vattr_context *context; /* vattr context */
- } roles_cache_build_result;
- /* Structure used to check if is_entry_member_of is part of a role defined in its suffix */
- typedef struct _roles_cache_search_in_nested
- {
- Slapi_Entry *is_entry_member_of;
- int present; /* flag to know if the entry is part of a role */
- int hint; /* to check the depth of the nested */
- } roles_cache_search_in_nested;
- /* Structure used to handle roles searches */
- typedef struct _roles_cache_search_roles
- {
- roles_cache_def *suffix_def;
- int rc; /* to check the depth of the nested */
- } roles_cache_search_roles;
- static roles_cache_def* roles_cache_create_suffix(Slapi_DN *sdn);
- static int roles_cache_add_roles_from_suffix(Slapi_DN *suffix_dn, roles_cache_def *suffix_def);
- static void roles_cache_wait_on_change(void * arg);
- static void roles_cache_trigger_update_suffix(void *handle, char *be_name, int old_be_state, int new_be_state);
- static void roles_cache_trigger_update_role(char *dn, Slapi_Entry *role_entry, Slapi_DN *be_dn, int operation);
- static int roles_cache_update(roles_cache_def *suffix_to_update);
- static int roles_cache_create_role_under(roles_cache_def** roles_cache_suffix, Slapi_Entry *entry);
- static int roles_cache_create_object_from_entry(Slapi_Entry *role_entry, role_object **result, int hint);
- static int roles_cache_determine_class(Slapi_Entry *role_entry);
- static int roles_cache_node_cmp( caddr_t d1, caddr_t d2 );
- static int roles_cache_insert_object(Avlnode **tree, role_object *object);
- static int roles_cache_node_nested_cmp( caddr_t d1, caddr_t d2 );
- static int roles_cache_insert_object_nested(Avlnode **tree, role_object_nested *object);
- static int roles_cache_object_nested_from_dn(Slapi_DN *role_dn, role_object_nested **result);
- static int roles_cache_build_nsrole( caddr_t data, caddr_t arg );
- static int roles_cache_find_node( caddr_t d1, caddr_t d2 );
- static int roles_cache_find_roles_in_suffix(Slapi_DN *target_entry_dn, roles_cache_def **list_of_roles);
- static int roles_is_entry_member_of_object(caddr_t data, caddr_t arg );
- static int roles_is_entry_member_of_object_ext(vattr_context *c, caddr_t data, caddr_t arg );
- static int roles_check_managed(Slapi_Entry *entry_to_check, role_object *role, int *present);
- static int roles_check_filtered(vattr_context *c, Slapi_Entry *entry_to_check, role_object *role, int *present);
- static int roles_check_nested(caddr_t data, caddr_t arg);
- static int roles_is_inscope(Slapi_Entry *entry_to_check, Slapi_DN *role_dn);
- static void berval_set_string(struct berval *bv, const char* string);
- static void roles_cache_role_def_delete(roles_cache_def *role_def);
- static void roles_cache_role_def_free(roles_cache_def *role_def);
- static void roles_cache_role_object_free(role_object *this_role);
- static void roles_cache_role_object_nested_free(role_object_nested *this_role);
- static int roles_cache_dump( caddr_t data, caddr_t arg );
- static int roles_cache_add_entry_cb(Slapi_Entry* e, void *callback_data);
- static void roles_cache_result_cb( int rc, void *callback_data);
- static Slapi_DN* roles_cache_get_top_suffix(Slapi_DN *suffix);
- /* ============== FUNCTIONS ================ */
- /* roles_cache_init
- ----------------
- create the cache for all the existing suffixes
- starts up the threads which wait for changes
- also registers vattr callbacks
- return 0 if OK
- return -1 otherwise
- */
- int roles_cache_init()
- {
- int rc = 0;
- void *node = NULL;
- Slapi_DN *sdn = NULL;
- roles_cache_def *new_suffix = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_init\n");
- if ( global_lock == NULL )
- {
- global_lock = PR_NewRWLock(0,"roles_cache");
- }
- /* grab the views interface */
- if(slapi_apib_get_interface(Views_v1_0_GUID, &views_api))
- {
- /* lets be tolerant if views is disabled */
- views_api = 0;
- }
- /* For each top suffix, get the roles definitions defined below it */
- PR_RWLock_Wlock(global_lock);
- sdn = slapi_get_first_suffix(&node, 0);
- while (sdn)
- {
- if ( (new_suffix = roles_cache_create_suffix(sdn)) == NULL )
- {
- PR_DestroyRWLock(global_lock);
- global_lock = NULL;
- return(-1);
- }
- if ( roles_cache_add_roles_from_suffix(sdn, new_suffix) != 0 )
- {
- /* No roles in that suffix, stop the thread and remove it ? */
- }
- sdn = slapi_get_next_suffix(&node, 0);
- }
- PR_RWLock_Unlock(global_lock);
- /* to expose roles_check to ACL plugin */
- slapi_register_role_check(roles_check);
- /* Register a callback on backends creation|modification|deletion,
- so that we update the corresponding cache */
- slapi_register_backend_state_change(NULL, roles_cache_trigger_update_suffix);
-
- if ( slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
- roles_sp_get_value,
- roles_sp_compare_value,
- roles_sp_list_types) )
- {
- slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_init: slapi_vattrspi_register failed\n");
- PR_DestroyRWLock(global_lock);
- global_lock = NULL;
- return(-1);
- }
- else if ( slapi_vattrspi_regattr(vattr_handle,NSROLEATTR,"", NULL) )
- {
- slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_init: slapi_vattrspi_regattr failed\n");
- slapi_ch_free((void **)&vattr_handle);
- PR_DestroyRWLock(global_lock);
- global_lock = NULL;
- return(-1);
- }
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_init\n");
- return rc;
- }
- /* roles_cache_create_suffix
- -------------------------
- Create a new entry in the global list
- return a pointer on the suffix stucture: OK
- return NULL: fail
- */
- static roles_cache_def *roles_cache_create_suffix(Slapi_DN *sdn)
- {
- roles_cache_def *current_suffix = NULL;
- roles_cache_def *new_suffix = NULL;
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_create_suffix\n");
- /* Allocate a new suffix block */
- new_suffix = (roles_cache_def*)slapi_ch_calloc(1, sizeof(roles_cache_def));
- if ( new_suffix == NULL )
- {
- slapi_log_error(SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_create_suffix: Unable to allocate memory, cannot create role cache\n");
- return(NULL);
- }
- new_suffix->cache_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "roles_def_lock");
- new_suffix->change_lock = slapi_new_mutex();
- new_suffix->stop_lock = slapi_new_mutex();
- new_suffix->create_lock = slapi_new_mutex();
- if ( new_suffix->stop_lock == NULL ||
- new_suffix->change_lock == NULL ||
- new_suffix->cache_lock == NULL ||
- new_suffix->create_lock == NULL )
- {
- slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_create_suffix: Lock creation failed\n");
- roles_cache_role_def_free(new_suffix);
- return(NULL);
- }
- new_suffix->something_changed = slapi_new_condvar(new_suffix->change_lock);
- if ( new_suffix->something_changed == NULL)
- {
- slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_create_suffix: Lock creation failed\n");
- roles_cache_role_def_free(new_suffix);
- return(NULL);
- }
- new_suffix->suffix_created = slapi_new_condvar(new_suffix->create_lock);
- if ( new_suffix->suffix_created == NULL)
- {
- slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_create_suffix: Lock creation failed\n");
- roles_cache_role_def_free(new_suffix);
- return(NULL);
- }
- new_suffix->keeprunning = 1;
- new_suffix->suffix_dn = slapi_sdn_dup(sdn);
- /* those 3 items are used to give back info to the thread when
- it is awakened */
- new_suffix->notified_dn = NULL;
- new_suffix->notified_entry = NULL;
- new_suffix->notified_operation = 0;
- /* Create the global list */
- if ( roles_list == NULL )
- {
- roles_list = new_suffix;
- }
- else
- {
- current_suffix = roles_list;
- while ( current_suffix != NULL )
- {
- if ( current_suffix->next == NULL )
- {
- current_suffix->next = new_suffix;
- break;
- }
- else
- {
- current_suffix = current_suffix->next;
- }
- }
- }
- /* to prevent deadlock */
- new_suffix->is_ready = 0;
- if ( (new_suffix->roles_tid = PR_CreateThread (PR_USER_THREAD,
- roles_cache_wait_on_change,
- (void*)new_suffix,
- PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD,
- SLAPD_DEFAULT_THREAD_STACKSIZE)) == NULL )
- {
- slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_create_suffix: PR_CreateThread failed\n");
- roles_cache_role_def_delete(new_suffix);
- return(NULL);
- }
- slapi_lock_mutex(new_suffix->create_lock);
- if (new_suffix->is_ready != 1)
- {
- slapi_wait_condvar(new_suffix->suffix_created, NULL);
- }
- slapi_unlock_mutex(new_suffix->create_lock);
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_create_suffix\n");
- return(new_suffix);
- }
- /* roles_cache_wait_on_change
- --------------------------
- Sit around waiting on a notification that something has
- changed, then fires off the updates
- */
- static void roles_cache_wait_on_change(void * arg)
- {
- roles_cache_def *roles_def = (roles_cache_def*)arg;
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_wait_on_change\n");
- slapi_lock_mutex(roles_def->stop_lock);
- slapi_lock_mutex(roles_def->change_lock);
- while ( roles_def->keeprunning)
- {
- slapi_unlock_mutex(roles_def->change_lock);
- slapi_lock_mutex(roles_def->change_lock);
- /* means that the thread corresponding to that suffix is ready to receive notifications
- from the server */
- slapi_lock_mutex(roles_def->create_lock);
- if ( roles_def->is_ready == 0 )
- {
- slapi_notify_condvar( roles_def->suffix_created, 1 );
- roles_def->is_ready = 1;
- }
- slapi_unlock_mutex(roles_def->create_lock);
- /* XXX In case the BE containing this role_def signaled
- a shut down between the unlock/lock above should
- test roles_def->keeprunning before
- going to sleep.
- */
- slapi_wait_condvar(roles_def->something_changed, NULL);
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "roles_cache_wait_on_change \n");
-
- if ( roles_def->keeprunning )
- {
- roles_cache_update(roles_def);
- }
- }
- /* shut down the cache */
- slapi_unlock_mutex(roles_def->change_lock);
- slapi_unlock_mutex(roles_def->stop_lock);
- roles_cache_role_def_free(roles_def);
-
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_wait_on_change thread exit\n");
- }
- /* roles_cache_trigger_update_suffix
- --------------------------------
- This is called when a backend changes state (created|modified|deleted)
- We simply signal to update the associated role cache in this case
- */
- static void roles_cache_trigger_update_suffix(void *handle, char *be_name, int old_be_state, int new_be_state)
- {
- roles_cache_def *current_role = roles_list;
- const Slapi_DN *be_suffix_dn = NULL;
- Slapi_DN *top_suffix_dn = NULL;
- Slapi_Backend *backend = NULL;
- int found = 0;
- PR_RWLock_Wlock(global_lock);
- if ( (new_be_state == SLAPI_BE_STATE_DELETE) || (new_be_state == SLAPI_BE_STATE_OFFLINE) )
- {
- /* Invalidate and rebuild the whole cache */
- roles_cache_def *current_role = NULL;
- roles_cache_def *next_role = NULL;
- Slapi_DN *sdn = NULL;
- void *node = NULL;
- roles_cache_def *new_suffix = NULL;
- /* Go through all the roles list and trigger the associated structure */
- current_role = roles_list;
- while ( current_role )
- {
- slapi_lock_mutex(current_role->change_lock);
- current_role->keeprunning = 0;
- next_role = current_role->next;
- slapi_notify_condvar(current_role->something_changed, 1 );
- slapi_unlock_mutex(current_role->change_lock);
- current_role = next_role;
- }
- /* rebuild a new one */
- roles_list = NULL;
- sdn = slapi_get_first_suffix(&node, 0);
- while (sdn)
- {
- if ( (new_suffix = roles_cache_create_suffix(sdn)) == NULL )
- {
- PR_RWLock_Unlock(global_lock);
- return;
- }
- roles_cache_add_roles_from_suffix(sdn, new_suffix);
- sdn = slapi_get_next_suffix(&node, 0);
- }
- PR_RWLock_Unlock(global_lock);
- return;
- }
-
- /* Backend back on line or new one created*/
- backend = slapi_be_select_by_instance_name(be_name);
- if ( backend != NULL )
- {
- be_suffix_dn = slapi_be_getsuffix(backend, 0);
- top_suffix_dn = roles_cache_get_top_suffix((Slapi_DN *)be_suffix_dn);
- }
-
- while ( (current_role != NULL) && !found && (top_suffix_dn != NULL) )
- {
- /* The backend already exists (back online): so invalidate "old roles definitions" */
- if ( slapi_sdn_compare(current_role->suffix_dn, top_suffix_dn) == 0 )
- {
- roles_cache_role_def_delete(current_role);
- found = 1;
- }
- else
- {
- current_role = current_role->next;
- }
- }
-
- if ( top_suffix_dn != NULL )
- {
- /* Add the new definitions in the cache */
- roles_cache_def *new_suffix = roles_cache_create_suffix(top_suffix_dn);
- if ( new_suffix != NULL )
- {
- roles_cache_add_roles_from_suffix(top_suffix_dn, new_suffix);
- }
- slapi_sdn_free(&top_suffix_dn);
- }
- PR_RWLock_Unlock(global_lock);
- }
- /* roles_cache_trigger_update_role
- --------------------------------
- Call when an entry containing a role definition has been added, modified
- or deleted
- */
- static void roles_cache_trigger_update_role(char *dn, Slapi_Entry *roles_entry, Slapi_DN *be_dn, int operation)
- {
- int found = 0;
- roles_cache_def *current_role = NULL;
- PR_RWLock_Wlock(global_lock);
-
- current_role = roles_list;
- slapi_log_error( SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_trigger_update_role: %x \n", roles_list);
- /* Go through all the roles list and trigger the associated structure */
-
- /* be_dn is already the top suffix for that dn */
- while ( (current_role != NULL) && !found )
- {
- if ( slapi_sdn_compare(current_role->suffix_dn, be_dn) == 0 )
- {
- found = 1;
- }
- else
- {
- current_role = current_role->next;
- }
- }
- if ( found )
- {
- slapi_lock_mutex(current_role->change_lock);
- slapi_entry_free (current_role->notified_entry);
- current_role->notified_entry = roles_entry;
- slapi_ch_free ((void**)&(current_role->notified_dn));
- current_role->notified_dn = dn;
- current_role->notified_operation = operation;
-
- roles_cache_update(current_role);
-
- slapi_unlock_mutex(current_role->change_lock);
- }
- PR_RWLock_Unlock(global_lock);
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_trigger_update_role: %x \n", roles_list);
- }
- /* roles_cache_update
- ------------------
- Update the cache associated to a suffix
- Return 0: ok
- Return -1: fail
- */
- static int roles_cache_update(roles_cache_def *suffix_to_update)
- {
- int rc = 0;
- int operation;
- Slapi_Entry *entry = NULL;
- Slapi_DN *dn = NULL;
- role_object *to_delete = NULL;
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_update \n");
- PR_RWLock_Wlock(suffix_to_update->cache_lock);
- operation = suffix_to_update->notified_operation;
- entry = suffix_to_update->notified_entry;
- dn = slapi_sdn_new();
- slapi_sdn_set_dn_byval(dn, suffix_to_update->notified_dn);
- if ( (entry != NULL) && (dn != NULL) )
- {
- if ( (operation == SLAPI_OPERATION_MODIFY) ||
- (operation == SLAPI_OPERATION_DELETE) )
- {
- /* delete it */
- int dummy;
- to_delete = (role_object *)avl_delete(&(suffix_to_update->avl_tree), dn, roles_cache_find_node, &dummy);
- roles_cache_role_object_free(to_delete);
- to_delete = NULL;
- if ( slapi_is_loglevel_set(SLAPI_LOG_PLUGIN) )
- {
- avl_apply(suffix_to_update->avl_tree, (IFP)roles_cache_dump, &rc, -1, AVL_INORDER);
- }
-
- }
- if ( (operation == SLAPI_OPERATION_MODIFY) ||
- (operation ==SLAPI_OPERATION_ADD) )
- {
- rc = roles_cache_create_role_under(&suffix_to_update,entry);
- }
- if ( entry != NULL )
- {
- slapi_entry_free(entry);
- }
- suffix_to_update->notified_entry = NULL;
- }
- PR_RWLock_Unlock(suffix_to_update->cache_lock);
- if ( dn != NULL )
- {
- slapi_sdn_free(&dn);
- }
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_update \n");
- return(rc);
- }
- /* roles_cache_stop
- ----------------
- XXX the stop_lock of a roles_cache_def
- doesn't seem to serve any useful purpose...
- */
- void roles_cache_stop()
- {
- roles_cache_def *current_role = NULL;
- roles_cache_def *next_role = NULL;
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_stop\n");
- /* Go through all the roles list and trigger the associated structure */
- PR_RWLock_Wlock(global_lock);
- current_role = roles_list;
- while ( current_role )
- {
- slapi_lock_mutex(current_role->change_lock);
- current_role->keeprunning = 0;
- next_role = current_role->next;
- slapi_notify_condvar(current_role->something_changed, 1 );
- slapi_unlock_mutex(current_role->change_lock);
- current_role = next_role;
- }
- PR_RWLock_Unlock(global_lock);
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_stop\n");
- }
- /* roles_cache_is_role_entry
- -------------------------
- Check if the entry is a role
- return -1: error in processing
- return 0: entry is not a role
- return 1: entry is a role
- */
- static int roles_cache_is_role_entry(struct slapi_entry *entry)
- {
- Slapi_Attr *pObjclasses = NULL;
- Slapi_Value *val = NULL;
- char *pObj = NULL;
- int index = 0;
- int nsroledefinition = 0;
- int nsrolesimpleOrComplex = 0;
- int nsroletype = 0;
- if ( entry == NULL )
- {
- return(0);
- }
- if ( slapi_entry_attr_find(entry, "objectclass", &pObjclasses) )
- {
- slapi_log_error( SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_is_role_entry: failed to get objectclass from %s\n",slapi_entry_get_dn_const(entry));
- return(-1);
- }
- /* Check out the object classes to see if this was a nsroledefinition */
-
- val = 0;
- index = slapi_attr_first_value( pObjclasses, &val );
- while(val)
- {
- const char *p;
- int len = 0;
- pObj = (char*)slapi_value_get_string(val);
-
- for ( p = pObj, len = 0;
- (*p != '\0') && (*p != ' ');
- p++, len++ )
- {
- ; /* NULL */
- }
- if ( !strncasecmp(pObj, (char*)"nsroledefinition", len) )
- {
- nsroledefinition = 1;
- }
- if ( !strncasecmp(pObj, (char*)"nssimpleroledefinition", len) ||
- !strncasecmp(pObj, (char*)"nscomplexroledefinition", len) )
- {
- nsrolesimpleOrComplex = 1;
- }
- if( !strncasecmp(pObj, (char*)"nsmanagedroledefinition", len) ||
- !strncasecmp(pObj, (char*)"nsfilteredroledefinition", len) ||
- !strncasecmp(pObj, (char*)"nsnestedroledefinition", len)
- )
- {
- nsroletype = 1;
- }
- index = slapi_attr_next_value( pObjclasses, index, &val );
- }
- if ( (nsroledefinition == 0) ||
- (nsrolesimpleOrComplex == 0) ||
- (nsroletype == 0) )
- {
- return(0);
- }
- return(1);
- }
- /* roles_cache_change_notify
- -------------------------
- determines if the change effects the cache and if so
- signals a rebuild
- -- called when modify|modrdn|add|delete operation is performed --
- -- called from a postoperation on an entry
- XXX this implies that the client may have already received his LDAP response,
- but that there will be a delay before he sees the effect in the roles cache.
- Should we be doing this processing in a BE_POST_MODIFY postop
- which is called _before_ the response goes to the client ?
- */
- void roles_cache_change_notify(Slapi_PBlock *pb)
- {
- char *dn = NULL;
- struct slapi_entry *e = NULL;
- struct slapi_entry *pre = NULL;
- struct slapi_entry *entry = NULL;
- Slapi_Backend *be = NULL;
- Slapi_Operation *pb_operation = NULL;
- int operation;
- int do_update = 0;
- int rc = -1;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM,
- "--> roles_cache_change_notify\n");
- /* if the current operation has failed, don't even try the post operation */
- slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &rc );
- if ( rc != LDAP_SUCCESS )
- {
- return;
- }
- /* Don't update local cache when remote entries are updated */
- slapi_pblock_get( pb, SLAPI_BACKEND, &be );
- if ( ( be!=NULL ) &&
- ( slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)) )
- {
- return;
- }
- slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- if( dn == NULL )
- {
- return;
- }
- slapi_pblock_get (pb, SLAPI_OPERATION, &pb_operation);
- operation = operation_get_type(pb_operation);
- switch (operation)
- {
- case SLAPI_OPERATION_DELETE:
- slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
- if( e == NULL )
- {
- return;
- }
- break;
- case SLAPI_OPERATION_ADD:
- slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
- if ( e == NULL )
- {
- return;
- }
- break;
- case SLAPI_OPERATION_MODIFY:
- case SLAPI_OPERATION_MODRDN:
- /* those operations are treated the same way and modify is a deletion followed by an addition.
- the only point to take care is that dn is the olddn */
- operation = SLAPI_OPERATION_MODIFY;
- slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &pre);
- if( pre == NULL )
- {
- return;
- }
- slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
- if ( e == NULL )
- {
- return;
- }
- break;
- default:
- slapi_log_error( SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_change_notify: unknown operation %d\n",operation);
- return;
- }
- if ( operation != SLAPI_OPERATION_MODIFY )
- {
- if ( roles_cache_is_role_entry(e) != 1 )
- {
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_change_notify: not a role entry\n");
- return;
- }
- entry = slapi_entry_dup(e);
- do_update = 1;
- }
- else
- {
- int is_pre_role = roles_cache_is_role_entry(pre);
- int is_post_role = roles_cache_is_role_entry(e);
- if ( (is_pre_role==1) && (is_post_role==1) ) /* role definition has changed */
- {
- entry = slapi_entry_dup(e);
- do_update = 1;
- }
- else if ( is_pre_role == 1 ) /* entry is no more a role */
- {
- operation = SLAPI_OPERATION_DELETE;
- do_update = 1;
- }
- else if ( is_post_role == 1 ) /* entry is now a role */
- {
- operation = SLAPI_OPERATION_ADD;
- entry = slapi_entry_dup(e);
- do_update = 1;
- }
- else
- {
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_change_notify: not a role entry\n");
- return;
- }
- }
-
- if ( do_update )
- {
- #ifdef moretrace
- if ( e != NULL )
- {
- Slapi_Attr *attr = NULL;
- int rc;
- /* Get the list of nested roles */
- rc = slapi_entry_attr_find(e,ROLE_NESTED_ATTR_NAME,&attr);
- if ( (rc == 0) && attr)
- {
- /* Recurse to get the definition objects for them */
- Slapi_Value **va = attr_get_present_values(attr);
- int i = 0;
- char *string = NULL;
-
- for ( i = 0; va[i] != NULL; i++ )
- {
- string = (char*)slapi_value_get_string(va[i]);
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "roles_cache_change_notify:%s\n",string);
- }
- }
- }
- #endif
- Slapi_DN *top_suffix = roles_cache_get_top_suffix(*(be->be_suffix));
- if ( top_suffix != NULL )
- {
- roles_cache_trigger_update_role( slapi_ch_strdup(dn), entry,
- top_suffix,
- operation);
- slapi_sdn_free(&top_suffix);
- }
- }
-
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_change_notify\n");
- }
- /* roles_cache_get_top_suffix
- -------------------------
- The returned Slapi_DN must be freed with slapi_sdn_free().
- */
- static Slapi_DN* roles_cache_get_top_suffix(Slapi_DN *suffix)
- {
- Slapi_DN *current_suffix = NULL;
- Slapi_DN parent_suffix;
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_get_top_suffix\n");
- if ( suffix == NULL )
- {
- return(NULL);
- }
- current_suffix = slapi_sdn_new();
- slapi_sdn_init(&parent_suffix);
- /* we must get the top suffix for that DN */
- slapi_sdn_copy(suffix,current_suffix);
- while ( !slapi_sdn_isempty(current_suffix) )
- {
- if ( slapi_is_root_suffix(current_suffix) != 1 )
- {
- slapi_sdn_get_parent(current_suffix,&parent_suffix);
- slapi_sdn_copy(&parent_suffix, current_suffix);
- }
- else
- {
- slapi_sdn_done(&parent_suffix);
- return(current_suffix);
- }
- }
- /* we should not return that way ... */
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_get_top_suffix\n");
- slapi_sdn_done(&parent_suffix);
- slapi_sdn_free(¤t_suffix);
- return(NULL);
- }
- /* roles_cache_add_roles_from_suffix
- -------------------------------
- Get the roles entries under the suffix
- return 0: OK
- return -1: this suffix has no role defined
- */
- static int roles_cache_add_roles_from_suffix(Slapi_DN *suffix_dn, roles_cache_def *suffix_def)
- {
- /* Search subtree-level under this entry */
- int rc = -1;
- roles_cache_search_roles info;
- Slapi_PBlock *int_search_pb = NULL;
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_add_roles_from_suffix\n");
-
- info.suffix_def = suffix_def;
- info.rc = LDAP_NO_SUCH_OBJECT;
- /* Get the roles definitions of the given suffix_dn */
- int_search_pb = slapi_pblock_new ();
- slapi_search_internal_set_pb(int_search_pb,
- (char*)slapi_sdn_get_ndn(suffix_dn),
- LDAP_SCOPE_SUBTREE,
- ROLE_DEFINITION_FILTER,
- allUserAttributes,
- 0 /* attrsonly */,
- NULL /* controls */,
- NULL /* uniqueid */,
- roles_get_plugin_identity(),
- SLAPI_OP_FLAG_NEVER_CHAIN /* actions : get local roles only */ );
- slapi_search_internal_callback_pb(int_search_pb,
- &info /* callback_data */,
- roles_cache_result_cb,
- roles_cache_add_entry_cb,
- NULL /* referral_callback */);
- slapi_pblock_destroy (int_search_pb);
- int_search_pb = NULL;
- if ( info.rc == LDAP_SUCCESS )
- {
- rc = 0;
- }
- slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_add_roles_from_suffix\n");
- return(rc);
- }
- /* roles_cache_add_entry_cb
- -----------------------
- */
- static int roles_cache_add_entry_cb(Slapi_Entry* e, void *callback_data)
- {
- roles_cache_search_roles *info=(roles_cache_search_roles *)callback_data;
- roles_cache_def *suffix = info->suffix_def;
-
- roles_cache_create_role_under(&suffix, e);
- return(0);
- }
- /* roles_cache_result_cb
- -----------------------
- */
- static void roles_cache_result_cb( int rc, void *callback_data) {
- roles_cache_search_roles *info=(roles_cache_search_roles *)callback_data;
-
- info->rc = rc;
- }
- /* roles_cache_create_role_under
- ----------------------------
- Create the avl tree of roles definitions defined in the scope
- of the suffix
- Return 0: OK
- Return -1: fail
- */
- static int roles_cache_create_role_under(roles_cache_def** roles_cache_suffix, Slapi_Entry *entry)
- {
- int rc;
- role_object *new_role = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_create_role_under: %s - %x\n",
- slapi_sdn_get_dn((*roles_cache_suffix)->suffix_dn),
- (*roles_cache_suffix)->avl_tree);
- rc = roles_cache_create_object_from_entry(entry,&new_role,0);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_create_role_under: create node for entry %s - rc: %d SUFFIX: %x\n",
- slapi_entry_get_dn_const(entry), rc, (*roles_cache_suffix)->avl_tree);
- if ( (rc == 0) && new_role)
- {
- /* Add to the tree where avl_data is a role_object struct */
- rc = roles_cache_insert_object(&((*roles_cache_suffix)->avl_tree),new_role);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_cache_create_role_under:%s in tree %x rc: %d\n",
- (char*)slapi_sdn_get_ndn(new_role->dn),
- (*roles_cache_suffix)->avl_tree, rc);
- }
- return(rc);
- }
- /* roles_cache_create_object_from_entry
- ------------------------------------
- Create a node role_object from the information contained in role_entry
- Return 0
- Return ENOMEM: fail
- Return SLAPI_ROLE_DEFINITION_ERROR: fail
- Return SLAPI_ROLE_ERROR_NO_FILTER_SPECIFIED: fail
- Return SLAPI_ROLE_ERROR_FILTER_BAD: fail
- */
- static int roles_cache_create_object_from_entry(Slapi_Entry *role_entry, role_object **result, int hint)
- {
- int rc = 0;
- int type = 0;
- role_object *this_role = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "--> roles_cache_create_object_from_entry\n");
- *result = NULL;
- /* Do not allow circular dependencies */
- if ( hint > MAX_NESTED_ROLES )
- {
- char *ndn = NULL;
- ndn = slapi_entry_get_ndn( role_entry );
- slapi_log_error(
- SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM,
- "Maximum roles nesting exceeded (%d), not retrieving roles from entry %s--probable circular definition\n",
- MAX_NESTED_ROLES,
- ndn);
- return (0);
- }
- /* Create the role cache definition */
- this_role = (role_object*)slapi_ch_calloc(1, sizeof(role_object));
- if (this_role == NULL )
- {
- return ENOMEM;
- }
- /* Check the entry is OK */
- /* Determine role type and assign to structure */
- /* We determine the role type by reading the objectclass */
- if ( roles_cache_is_role_entry(role_entry) == 0 )
- {
- /* Bad type */
- slapi_ch_free((void**)&this_role);
- return SLAPI_ROLE_DEFINITION_ERROR;
- }
- type = roles_cache_determine_class(role_entry);
- if (type != 0)
- {
- this_role->type = type;
- }
- else
- {
- /* Bad type */
- slapi_ch_free((void**)&this_role);
- return SLAPI_ROLE_DEFINITION_ERROR;
- }
- this_role->dn = slapi_sdn_new();
- slapi_sdn_copy(slapi_entry_get_sdn(role_entry),this_role->dn);
- /* Depending upon role type, pull out the remaining information we need */
- switch (this_role->type)
- {
- case ROLE_TYPE_MANAGED:
- /* Nothing further needed */
- break;
- case ROLE_TYPE_FILTERED:
- {
- Slapi_Filter *filter = NULL;
- char *filter_attr_value = NULL;
- /* Get the filter and retrieve the filter attribute */
- filter_attr_value = slapi_entry_attr_get_charptr(role_entry,ROLE_FILTER_ATTR_NAME);
- if ( filter_attr_value == NULL )
- {
- /* Means probably no attribute or no value there */
- slapi_ch_free((void**)&this_role);
- return SLAPI_ROLE_ERROR_NO_FILTER_SPECIFIED;
- }
- /* Turn it into a slapi filter object */
- filter = slapi_str2filter(filter_attr_value);
- slapi_ch_free((void**)&filter_attr_value);
- if ( filter == NULL )
- {
- /* An error has occured */
- slapi_ch_free((void**)&this_role);
- return SLAPI_ROLE_ERROR_FILTER_BAD;
- }
- /* Store on the object */
- this_role->filter = filter;
- break;
- }
- case ROLE_TYPE_NESTED:
- {
- Slapi_Attr *attr = NULL;
- /* Get the list of nested roles */
- rc = slapi_entry_attr_find(role_entry,ROLE_NESTED_ATTR_NAME,&attr);
- if ( (rc == 0) && attr)
- {
- /* Recurse to get the definition objects for them */
- Slapi_Value **va = attr_get_present_values(attr);
- int i = 0;
- char *string = NULL;
- Slapi_DN nested_role_dn;
- role_object_nested *nested_role_object = NULL;
-
- for ( i = 0; va[i] != NULL; i++ )
- {
- string = (char*)slapi_value_get_string(va[i]);
- /* Make a DN from the string */
- slapi_sdn_init_dn_byref(&nested_role_dn,string);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_cache_create_object_from_entry: dn %s, nested %s\n",
- (char*)slapi_sdn_get_ndn(this_role->dn),string);
- /* Make a role object nested from the DN */
- rc = roles_cache_object_nested_from_dn(&nested_role_dn,&nested_role_object);
- /* Insert it into the nested list */
- if ( (rc == 0) && nested_role_object)
- {
- /* Add to the tree where avl_data is a role_object_nested struct */
- rc = roles_cache_insert_object_nested(&(this_role->avl_tree),nested_role_object);
- }
- slapi_sdn_done(&nested_role_dn);
- }
- }
-
- break;
- }
- default:
- slapi_log_error(SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM, "wrong role type\n");
- }
- if ( rc == 0 )
- {
- *result = this_role;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "<-- roles_cache_create_object_from_entry\n");
- return rc;
- }
- /* roles_cache_determine_class:
- ----------------------------
- Determine the type of role depending on the objectclass
- Return the type of the role
- */
- static int roles_cache_determine_class(Slapi_Entry *role_entry)
- {
- /* Examine the entry's objectclass attribute */
- int found_managed = 0;
- int found_filtered = 0;
- int found_nested = 0;
- Slapi_Attr *attr= NULL;
- struct berval bv = {0};
- int rc = 0;
- int type = 0;
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "--> roles_cache_determine_class\n");
- rc = slapi_entry_attr_find(role_entry,"objectclass",&attr);
- if ( rc != 0 )
- {
- /* No objectclass, definitely an error */
- return 0;
- }
- berval_set_string(&bv,ROLE_OBJECTCLASS_MANAGED);
- rc = slapi_attr_value_find(attr,&bv);
- if ( rc == 0 )
- {
- found_managed = 1;
- type = ROLE_TYPE_MANAGED;
- }
- berval_set_string(&bv,ROLE_OBJECTCLASS_FILTERED);
- rc = slapi_attr_value_find(attr,&bv);
- if ( rc == 0 )
- {
- found_filtered = 1;
- type = ROLE_TYPE_FILTERED;
- }
- berval_set_string(&bv,ROLE_OBJECTCLASS_NESTED);
- rc = slapi_attr_value_find(attr,&bv);
- if ( rc == 0 )
- {
- found_nested = 1;
- type = ROLE_TYPE_NESTED;
- }
-
- if ( (found_managed + found_nested + found_filtered) > 1 )
- {
- /* Means some goofball configured a role definition which is trying to be more than one different type. error. */
- return 0;
- }
- if ( (found_managed + found_nested + found_filtered) == 0)
- {
- /* Means this entry isn't any of the role types we handle. error. */
- return 0;
- }
-
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "<-- roles_cache_determine_class\n");
- /* Return the appropriate type ordinal */
- return type;
- }
- /* roles_cache_node_cmp:
- ---------------------
- Comparison function to add a new node in the avl tree (avl_data is of type role_object)
- */
- static int roles_cache_node_cmp( caddr_t d1, caddr_t d2 )
- {
- role_object *role_to_insert = (role_object*)d1;
- role_object *current_role = (role_object*)d2;
- /* role_to_insert and current_role are never NULL in that context */
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_node_cmp\n");
- return (slapi_sdn_compare((Slapi_DN *)role_to_insert->dn, (Slapi_DN *)current_role->dn));
- }
- /* roles_cache_insert_object:
- --------------------------
- Insert a new node in the avl tree of a specific suffix
- */
- static int roles_cache_insert_object(Avlnode **tree, role_object *object)
- {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_cache_insert_object: %s in tree %x\n",
- (char*)slapi_sdn_get_ndn(object->dn),
- *tree);
- return (avl_insert(tree, (caddr_t)object, roles_cache_node_cmp, avl_dup_error));
- }
- /* roles_cache_node_nested_cmp:
- ----------------------------
- Comparison function to add a new node in the avl tree
- */
- static int roles_cache_node_nested_cmp( caddr_t d1, caddr_t d2 )
- {
- role_object_nested *role_to_insert = (role_object_nested*)d1;
- role_object_nested *current_role = (role_object_nested*)d2;
- /* role_to_insert and current_role are never NULL in that context */
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "roles_cache_node_nested_cmp\n");
- return slapi_sdn_compare(role_to_insert->dn, current_role->dn);
- }
- /* roles_cache_insert_object_nested:
- ---------------------------------
- Insert a new node in the avl tree of a specific suffix
- */
- static int roles_cache_insert_object_nested(Avlnode **tree, role_object_nested *object)
- {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_cache_insert_object_nested: %s in tree %x: \n",
- (char*)slapi_sdn_get_ndn(object->dn), *tree);
- return (avl_insert(tree, (caddr_t)object, roles_cache_node_nested_cmp, avl_dup_error));
- }
- /* roles_cache_object_nested_from_dn
- ----------------------------------
- Get the role associated to an entry DN
- Return 0: OK
- Return ENOMEM: fail
- */
- static int roles_cache_object_nested_from_dn(Slapi_DN *role_dn, role_object_nested **result)
- {
- role_object_nested *nested_role = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "--> roles_cache_object_nested_from_dn\n");
- *result = NULL;
- /* Create the role cache definition */
- nested_role = (role_object_nested*)slapi_ch_calloc(1, sizeof(role_object_nested));
- if (nested_role == NULL )
- {
- return ENOMEM;
- }
- nested_role->dn = slapi_sdn_new();
- slapi_sdn_copy(role_dn,nested_role->dn);
- *result = nested_role;
- slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
- "<-- roles_cache_object_nested_from_dn\n");
- return 0;
- }
- /* roles_cache_listroles
- --------------------
- Lists all the roles an entry posesses
- return_values = 0 means that we don't need the nsrole values
- return_values = 1 means that we need the nsrole values
- Return 0: the entry has nsrole
- Return -1: the entry has no nsrole
- */
- int roles_cache_listroles(Slapi_Entry *entry, int return_values, Slapi_ValueSet **valueset_out)
- {
- return roles_cache_listroles_ext(NULL, entry, return_values, valueset_out);
- }
- int roles_cache_listroles_ext(vattr_context *c, Slapi_Entry *entry, int return_values, Slapi_ValueSet **valueset_out)
- {
- roles_cache_def *roles_cache = NULL;
- int rc = 0;
- roles_cache_build_result arg;
- Slapi_Backend *backend = NULL;
-
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_listroles\n");
- backend = slapi_mapping_tree_find_backend_for_sdn(slapi_entry_get_sdn(entry));
- if ( (backend != NULL) && slapi_be_is_flag_set(backend,SLAPI_BE_FLAG_REMOTE_DATA) )
- {
- /* the entry is not local, so don't return anything */
- return (-1);
- }
-
- if ( return_values )
- {
- *valueset_out = (Slapi_ValueSet*)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
- slapi_valueset_init(*valueset_out);
- }
-
- /* First get a list of all the in-scope roles */
- /* XXX really need a mutex for this read operation ? */
- PR_RWLock_Rlock(global_lock);
- rc = roles_cache_find_roles_in_suffix( slapi_entry_get_sdn(entry),&roles_cache);
- PR_RWLock_Unlock(global_lock);
- /* Traverse the tree checking if the entry has any of the roles */
- if ( roles_cache != NULL )
- {
- if ( roles_cache->avl_tree )
- {
- arg.nsrole_values = valueset_out;
- arg.need_value = return_values;
- arg.requested_entry = entry;
- arg.has_value = 0;
- arg.context = c;
- /* XXX really need a mutex for this read operation ? */
- PR_RWLock_Rlock(roles_cache->cache_lock);
- avl_apply(roles_cache->avl_tree, (IFP)roles_cache_build_nsrole, &arg, -1, AVL_INORDER);
- PR_RWLock_Unlock(roles_cache->cache_lock);
-
- if( !arg.has_value )
- {
- if ( return_values )
- {
- slapi_valueset_free(*valueset_out);
- *valueset_out = NULL;
- }
- rc = -1;
- }
- /* Free the list (we already did that) */
- }
- else
- {
- if ( return_values )
- {
- slapi_valueset_free(*valueset_out);
- *valueset_out = NULL;
- }
- rc = -1;
- }
- }
- else
- {
- /* no roles associated */
- rc = -1;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_listroles\n");
- return rc;
- }
- /* roles_cache_build_nsrole
- ------------------------
- Traverse the tree containing roles definitions for a suffix and for each
- one of them, check wether the entry is a member of it or not
- For ones which check out positive, we add their DN to the value
- always return 0 to allow to trverse all the tree
- */
- static int roles_cache_build_nsrole( caddr_t data, caddr_t arg )
- {
- Slapi_Value *value = NULL;
- roles_cache_build_result *result = (roles_cache_build_result*)arg;
- role_object *this_role = (role_object*)data;
- roles_cache_search_in_nested get_nsrole;
- /* Return a value different from the stop flag to be able
- to go through all the tree */
- int rc = 0;
- int tmprc = 0;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_build_nsrole: role %s\n",
- (char*) slapi_sdn_get_ndn(this_role->dn));
- value = slapi_value_new_string("");
-
- get_nsrole.is_entry_member_of = result->requested_entry;
- get_nsrole.present = 0;
- get_nsrole.hint = 0;
- tmprc = roles_is_entry_member_of_object_ext(result->context, (caddr_t)this_role, (caddr_t)&get_nsrole);
- if (SLAPI_VIRTUALATTRS_LOOP_DETECTED == tmprc)
- {
- /* all we want to detect and return is loop/stack overflow */
- rc = tmprc;
- }
-
- /* If so, add its DN to the attribute */
- if (get_nsrole.present)
- {
- result->has_value = 1;
- if ( result->need_value )
- {
- slapi_value_set_string(value,(char*) slapi_sdn_get_ndn(this_role->dn));
- slapi_valueset_add_value(*(result->nsrole_values),value);
- }
- else
- {
- /* we don't need the value but we already know there is one nsrole.
- stop the traversal
- */
- rc = -1;
- }
- }
-
- slapi_value_free(&value);
-
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_build_nsrole\n");
- return rc;
- }
- /* roles_check
- -----------
- Checks if an entry has a presented role, assuming that we've already verified
- that
- the role both exists and is in scope
- return 0: no processing error
- return -1: error
- */
- int roles_check(Slapi_Entry *entry_to_check, Slapi_DN *role_dn, int *present)
- {
- roles_cache_def *roles_cache = NULL;
- role_object *this_role = NULL;
- roles_cache_search_in_nested get_nsrole;
- int rc = 0;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_check\n");
- *present = 0;
- PR_RWLock_Rlock(global_lock);
- if ( roles_cache_find_roles_in_suffix(slapi_entry_get_sdn(entry_to_check),
- &roles_cache) != 0 )
- {
- PR_RWLock_Unlock(global_lock);
- return -1;
- }
- PR_RWLock_Unlock(global_lock);
- this_role = (role_object *)avl_find(roles_cache->avl_tree, role_dn, (IFP)roles_cache_find_node);
- /* MAB: For some reason the assumption made by this function (the role exists and is in scope)
- * does not seem to be true... this_role might be NULL after the avl_find call (is the avl_tree
- * broken? Anyway, this is crashing the 5.1 server on 29-Aug-01, so I am applying the following patch
- * to avoid the crash inside roles_is_entry_member_of_object */
- /* Begin patch */
- if (!this_role) {
- /* Assume that the entry is not member of the role (*present=0) and leave... */
- return rc;
- }
- /* End patch */
- get_nsrole.is_entry_member_of = entry_to_check;
- get_nsrole.present = 0;
- get_nsrole.hint = 0;
- roles_is_entry_member_of_object((caddr_t)this_role, (caddr_t)&get_nsrole);
- *present = get_nsrole.present;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_check\n");
- return rc;
- }
- /* roles_cache_find_node:
- ---------------------
- Comparison function to add a new node in the avl tree
- */
- static int roles_cache_find_node( caddr_t d1, caddr_t d2 )
- {
- Slapi_DN *data = (Slapi_DN *)d1;
- role_object *role= (role_object *)d2;
- /* role is not NULL in that context */
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_cache_find_node: %s %s\n",
- slapi_sdn_get_dn(data), slapi_sdn_get_dn(role->dn));
- return (slapi_sdn_compare(data, (Slapi_DN *)role->dn));
- }
- /* roles_cache_find_roles_in_suffix
- -------------------------------
- Find all the roles in scope to an entry
- */
- static int roles_cache_find_roles_in_suffix(Slapi_DN *target_entry_dn, roles_cache_def **list_of_roles)
- {
- int rc = -1;
- Slapi_Backend *backend = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_find_roles_in_suffix\n");
- *list_of_roles = NULL;
- backend = slapi_mapping_tree_find_backend_for_sdn(target_entry_dn);
- if ( (backend != NULL) && !slapi_be_is_flag_set(backend,SLAPI_BE_FLAG_REMOTE_DATA) )
- {
- Slapi_DN *suffix = roles_cache_get_top_suffix(*(backend->be_suffix));
- roles_cache_def *current_role = roles_list;
- /* Go through all the roles list and trigger the associated structure */
- while ( (current_role != NULL) && (suffix != NULL) )
- {
- if ( slapi_sdn_compare(current_role->suffix_dn, suffix) == 0 )
- {
- *list_of_roles = current_role;
- /* OK, we have found one */
- slapi_sdn_free(&suffix);
- return 0;
- }
- else
- {
- current_role = current_role->next;
- }
- }
- if ( suffix != NULL )
- {
- slapi_sdn_free(&suffix);
- }
- /* If we got out that way, means that we didn't have find
- roles definitions for that suffix */
- return rc;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_find_roles_in_suffix\n");
- return rc;
- }
- /* roles_is_entry_member_of_object
- --------------------------------
- Check if the entry is part of a role defined in its suffix
- return 0: ok
- return 1: fail
- -> to check the presence, see present
- */
- static int roles_is_entry_member_of_object(caddr_t data, caddr_t argument )
- {
- return roles_is_entry_member_of_object_ext(NULL, data, argument );
- }
- static int roles_is_entry_member_of_object_ext(vattr_context *c, caddr_t data, caddr_t argument )
- {
- int rc = -1;
- roles_cache_search_in_nested *get_nsrole = (roles_cache_search_in_nested*)argument;
- role_object *this_role = (role_object*)data;
- Slapi_Entry *entry_to_check = get_nsrole->is_entry_member_of;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_is_entry_member_of_object\n");
- if (!roles_is_inscope(entry_to_check, this_role->dn))
- {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_is_entry_member_of_object-> entry not in scope of role\n");
- return rc;
- }
- if ( this_role != NULL )
- {
- /* Determine the role type */
- switch (this_role->type)
- {
- case ROLE_TYPE_MANAGED:
- rc = roles_check_managed(entry_to_check,this_role,&get_nsrole->present);
- break;
- case ROLE_TYPE_FILTERED:
- rc = roles_check_filtered(c, entry_to_check,this_role,&get_nsrole->present);
- break;
- case ROLE_TYPE_NESTED:
- {
- /* Go through the tree of the nested DNs */
- get_nsrole->hint++;
- avl_apply(this_role->avl_tree, (IFP)roles_check_nested, get_nsrole, 0, AVL_INORDER);
- get_nsrole->hint--;
- /* kexcoff?? */
- rc = get_nsrole->present;
- break;
- }
- default:
- slapi_log_error(SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM, "roles_is_entry_member_of_object-> invalid role type\n");
- }
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_is_entry_member_of_object\n");
- return rc;
- }
- /* roles_check_managed
- -------------------------
- Check a managed role: we just need to check the content of the entry's nsRoleDN attribute
- against the role DN
- return 0: ok
- return 1: fail
- -> to check the presence, see present
- */
- static int roles_check_managed(Slapi_Entry *entry_to_check, role_object *role, int *present)
- {
- int rc = 0;
- Slapi_Attr *attr = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_check_managed\n");
- /* Get the attribute */
- rc = slapi_entry_attr_find(entry_to_check,ROLE_MANAGED_ATTR_NAME,&attr);
- if ( rc == 0)
- {
- struct berval bv = {0};
- char *dn_string = NULL;
- /* Check content against the presented DN */
- /* We assume that this function handles normalization and so on */
- dn_string = (char*) slapi_sdn_get_ndn(role->dn);
- berval_set_string(&bv,dn_string);
- rc = slapi_attr_value_find(attr,&bv);
- if ( rc == 0 )
- {
- *present = 1;
- }
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM,
- "<-- roles_check_managed: entry %s role %s present %d\n",
- slapi_entry_get_dn_const(entry_to_check),(char*)slapi_sdn_get_ndn(role->dn),*present);
- return rc;
- }
- /* roles_check_filtered
- --------------------------
- Check a filtered role: call slapi_filter_test here on the entry
- and the filter from the role object
- return 0: ok
- return 1: fail
- -> to check the presence, see present
- */
- static int roles_check_filtered(vattr_context *c, Slapi_Entry *entry_to_check, role_object *role, int *present)
- {
- int rc = 0;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_check_filtered\n");
- rc = slapi_vattr_filter_test_ext(slapi_vattr_get_pblock_from_context(c),
- entry_to_check, role->filter, 0, 0);
- if ( rc == 0 )
- {
- *present = 1;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM,
- "<-- roles_check_filtered: entry %s role %s present %d\n",
- slapi_entry_get_dn_const(entry_to_check),(char*)slapi_sdn_get_ndn(role->dn),*present);
- return rc;
- }
- /* roles_check_nested
- ------------------------
- Check a nested role
- return 0: ok
- return -1: fail
- -> to check the presence, see present
- */
- static int roles_check_nested(caddr_t data, caddr_t arg)
- {
- roles_cache_search_in_nested *get_nsrole = (roles_cache_search_in_nested*)arg;
- int rc = -1;
- role_object_nested *current_nested_role = (role_object_nested*)data;
- /* do not allow circular dependencies, the cheap and easy way */
- if( get_nsrole->hint > MAX_NESTED_ROLES)
- {
- char *ndn = NULL;
- ndn = slapi_entry_get_ndn( get_nsrole->is_entry_member_of );
- slapi_log_error(SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM,
- "Maximum roles nesting exceeded (max %d current %d), not checking roles in entry %s--probable circular definition\n",
- MAX_NESTED_ROLES,
- get_nsrole->hint,
- ndn);
- /* Stop traversal value */
- return 0;
- }
- /* Here we traverse the list of nested roles, calling the appropriate
- evaluation function for those in turn */
- if (current_nested_role)
- {
- roles_cache_def *roles_cache = NULL;
- role_object *this_role = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM,
- "-->roles_check_nested: entry %s role %s present %d\n",
- slapi_entry_get_dn_const(get_nsrole->is_entry_member_of),
- (char*)slapi_sdn_get_ndn(current_nested_role->dn),
- get_nsrole->present);
- if ( roles_cache_find_roles_in_suffix(current_nested_role->dn,
- &roles_cache) != 0 )
- {
- return rc;
- }
- if ( slapi_is_loglevel_set(SLAPI_LOG_PLUGIN) )
- {
- avl_apply(roles_cache->avl_tree, (IFP)roles_cache_dump, &rc, -1, AVL_INORDER);
- }
- this_role = (role_object *)avl_find(roles_cache->avl_tree,
- current_nested_role->dn,
- (IFP)roles_cache_find_node);
- if ( this_role == NULL )
- {
- /* the nested role doesn't exist */
- slapi_log_error(SLAPI_LOG_FATAL,
- ROLES_PLUGIN_SUBSYSTEM,
- "The nested role %s doesn't exist\n",
- (char*)slapi_sdn_get_ndn(current_nested_role->dn));
- return rc;
- }
- /* get the role_object data associated to that dn */
- if ( roles_is_inscope(get_nsrole->is_entry_member_of, this_role->dn) )
- {
- /* The list of nested roles is contained in the role definition */
- roles_is_entry_member_of_object((caddr_t)this_role, (caddr_t)get_nsrole);
- if ( get_nsrole->present == 1 )
- {
- return 0;
- }
- }
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_check_nested\n");
- return rc;
- }
- /* roles_is_inscope
- ----------------------
- Tells us if a presented role is in scope with respect to the presented entry
- */
- static int roles_is_inscope(Slapi_Entry *entry_to_check, Slapi_DN *role_dn)
- {
- int rc;
- Slapi_DN role_parent;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_is_inscope\n");
- slapi_sdn_init(&role_parent);
- slapi_sdn_get_parent(role_dn,&role_parent);
- rc = slapi_sdn_scope_test(slapi_entry_get_sdn( entry_to_check ),
- &role_parent,
- LDAP_SCOPE_SUBTREE);
- /* we need to check whether the entry would be returned by a view in scope */
- if(!rc && views_api)
- {
- rc = views_entry_exists(views_api, (char*)slapi_sdn_get_ndn(&role_parent), entry_to_check);
- }
- slapi_sdn_done(&role_parent);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_is_inscope: entry %s role %s result %d\n",
- slapi_entry_get_dn_const(entry_to_check),(char*)slapi_sdn_get_ndn(role_dn), rc);
- return (rc);
- }
- static void berval_set_string(struct berval *bv, const char* string)
- {
- bv->bv_len= strlen(string);
- bv->bv_val= (void*)string; /* We cast away the const, but we're not going to change anything
- */
- }
- /* roles_cache_role_def_delete
- ----------------------------
- */
- static void roles_cache_role_def_delete(roles_cache_def *role_def)
- {
- roles_cache_def *current = roles_list;
- roles_cache_def *previous = NULL;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_def_delete\n");
- while ( current!= NULL )
- {
- if ( slapi_sdn_compare(current->suffix_dn, role_def->suffix_dn) == 0 )
- {
- if ( previous== NULL )
- {
- roles_list = current->next;
- }
- else
- {
- previous->next = current->next;
- }
- slapi_lock_mutex(role_def->change_lock);
- role_def->keeprunning = 0;
- slapi_notify_condvar(role_def->something_changed, 1 );
- slapi_unlock_mutex(role_def->change_lock);
- break;
- }
- else
- {
- previous = current;
- current = current->next;
- }
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_def_delete\n");
- }
- /* roles_cache_role_def_free
- ----------------------------
- */
- static void roles_cache_role_def_free(roles_cache_def *role_def)
- {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_def_free\n");
- if ( role_def == NULL )
- {
- return;
- }
- slapi_lock_mutex(role_def->stop_lock);
- avl_free(role_def->avl_tree, (IFP)roles_cache_role_object_free);
- slapi_sdn_free(&(role_def->suffix_dn));
- PR_DestroyRWLock(role_def->cache_lock);
- role_def->cache_lock = NULL;
- slapi_destroy_mutex(role_def->change_lock);
- role_def->change_lock = NULL;
- slapi_destroy_condvar(role_def->something_changed);
- slapi_destroy_mutex(role_def->create_lock);
- role_def->create_lock = NULL;
- slapi_destroy_condvar(role_def->suffix_created);
- slapi_ch_free((void**)&role_def->notified_dn);
- if ( role_def->notified_entry != NULL )
- {
- slapi_entry_free(role_def->notified_entry);
- }
- slapi_unlock_mutex(role_def->stop_lock);
- slapi_destroy_mutex(role_def->stop_lock);
- role_def->stop_lock = NULL;
- slapi_ch_free((void**)&role_def);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_def_free\n");
- }
- /* roles_cache_role_object_free
- ----------------------------
- */
- static void roles_cache_role_object_free(role_object *this_role)
- {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_object_free\n");
- if ( this_role == NULL )
- {
- return;
- }
- switch (this_role->type)
- {
- case ROLE_TYPE_MANAGED:
- /* Nothing further needed */
- break;
- case ROLE_TYPE_FILTERED:
- /* Free the filter */
- if (this_role->filter)
- {
- slapi_filter_free(this_role->filter,1);
- this_role->filter = NULL;
- }
- break;
- case ROLE_TYPE_NESTED:
- /* Free the list of nested roles */
- {
- avl_free(this_role->avl_tree, roles_cache_role_object_nested_free);
- }
- break;
- }
- slapi_sdn_free(&this_role->dn);
- /* Free the object */
- slapi_ch_free((void**)&this_role);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_object_free\n");
- }
- /* roles_cache_role_object_nested_free
- ------------------------------------
- */
- static void roles_cache_role_object_nested_free(role_object_nested *this_role)
- {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_object_nested_free\n");
- if ( this_role == NULL )
- {
- return;
- }
- slapi_sdn_free(&this_role->dn);
- /* Free the object */
- slapi_ch_free((void**)&this_role);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_object_nested_free\n");
- }
- static int roles_cache_dump( caddr_t data, caddr_t arg )
- {
- role_object *this_role = (role_object*)data;
-
- slapi_log_error(SLAPI_LOG_PLUGIN,
- ROLES_PLUGIN_SUBSYSTEM, "roles_cache_dump: %x - %s - %x\n",
- this_role, (char*)slapi_sdn_get_ndn(this_role->dn), this_role->avl_tree);
-
- return 0;
- }
|