roles_cache.c 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include <sys/types.h>
  44. #include "portable.h"
  45. #include "slapi-plugin.h"
  46. #include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
  47. #include "dirver.h"
  48. /* This is naughty ... */
  49. #include "slapi-private.h"
  50. /* include NSPR header files */
  51. #include "slap.h"
  52. #include "prthread.h"
  53. #include "prlock.h"
  54. #include "prerror.h"
  55. #include "prcvar.h"
  56. #include "prio.h"
  57. #include "avl.h"
  58. #include "vattr_spi.h"
  59. #include "roles_cache.h"
  60. #include "views.h"
  61. #ifdef SOLARIS
  62. #include <tnf/probe.h>
  63. #else
  64. #define TNF_PROBE_0(a,b,c)
  65. #endif
  66. #define MAX_NESTED_ROLES 30
  67. static char *allUserAttributes[] = {
  68. LDAP_ALL_USER_ATTRS,
  69. NULL
  70. };
  71. /* views scoping */
  72. static void **views_api;
  73. /* Service provider handler */
  74. static vattr_sp_handle *vattr_handle = NULL;
  75. /* List of nested roles */
  76. typedef struct _role_object_nested {
  77. Slapi_DN *dn; /* value of attribute nsroledn in a nested role definition */
  78. } role_object_nested;
  79. /* Role object structure */
  80. typedef struct _role_object {
  81. Slapi_DN *dn; /* dn of a role entry */
  82. int type; /* ROLE_TYPE_MANAGED|ROLE_TYPE_FILTERED|ROLE_TYPE_NESTED */
  83. Slapi_Filter *filter; /* if ROLE_TYPE_FILTERED */
  84. Avlnode *avl_tree; /* if ROLE_TYPE_NESTED: tree of nested DNs (avl_data is a role_object_nested struct) */
  85. } role_object;
  86. /* Structure containing the roles definitions for a given suffix */
  87. typedef struct _roles_cache_def {
  88. /* Suffix DN*/
  89. Slapi_DN *suffix_dn;
  90. /* Module level thread control */
  91. PRThread *roles_tid;
  92. int keeprunning;
  93. PRRWLock *cache_lock;
  94. Slapi_Mutex *stop_lock;
  95. Slapi_Mutex *change_lock;
  96. Slapi_CondVar *something_changed;
  97. Slapi_Mutex *create_lock;
  98. Slapi_CondVar *suffix_created;
  99. int is_ready;
  100. /* Root of the avl tree containing all the roles definitions
  101. NB: avl_data field is of type role_object
  102. */
  103. Avlnode *avl_tree;
  104. /* Next roles suffix definitions */
  105. struct _roles_cache_def *next;
  106. /* Info passed from the server when an notification is sent to the plugin */
  107. char *notified_dn;
  108. Slapi_Entry *notified_entry;
  109. int notified_operation;
  110. } roles_cache_def;
  111. /* Global list containing all the roles definitions per suffix */
  112. static roles_cache_def *roles_list = NULL;
  113. static PRRWLock *global_lock = NULL;
  114. /* Structure holding the nsrole values */
  115. typedef struct _roles_cache_build_result
  116. {
  117. Slapi_ValueSet **nsrole_values; /* nsrole computed values */
  118. Slapi_Entry *requested_entry; /* entry to get nsrole from */
  119. int has_value; /* flag to determine if a new value has been added to the result */
  120. int need_value; /* flag to determine if we need the result */
  121. vattr_context *context; /* vattr context */
  122. } roles_cache_build_result;
  123. /* Structure used to check if is_entry_member_of is part of a role defined in its suffix */
  124. typedef struct _roles_cache_search_in_nested
  125. {
  126. Slapi_Entry *is_entry_member_of;
  127. int present; /* flag to know if the entry is part of a role */
  128. int hint; /* to check the depth of the nested */
  129. } roles_cache_search_in_nested;
  130. /* Structure used to handle roles searches */
  131. typedef struct _roles_cache_search_roles
  132. {
  133. roles_cache_def *suffix_def;
  134. int rc; /* to check the depth of the nested */
  135. } roles_cache_search_roles;
  136. static roles_cache_def* roles_cache_create_suffix(Slapi_DN *sdn);
  137. static int roles_cache_add_roles_from_suffix(Slapi_DN *suffix_dn, roles_cache_def *suffix_def);
  138. static void roles_cache_wait_on_change(void * arg);
  139. static void roles_cache_trigger_update_suffix(void *handle, char *be_name, int old_be_state, int new_be_state);
  140. static void roles_cache_trigger_update_role(char *dn, Slapi_Entry *role_entry, Slapi_DN *be_dn, int operation);
  141. static int roles_cache_update(roles_cache_def *suffix_to_update);
  142. static int roles_cache_create_role_under(roles_cache_def** roles_cache_suffix, Slapi_Entry *entry);
  143. static int roles_cache_create_object_from_entry(Slapi_Entry *role_entry, role_object **result, int hint);
  144. static int roles_cache_determine_class(Slapi_Entry *role_entry);
  145. static int roles_cache_node_cmp( caddr_t d1, caddr_t d2 );
  146. static int roles_cache_insert_object(Avlnode **tree, role_object *object);
  147. static int roles_cache_node_nested_cmp( caddr_t d1, caddr_t d2 );
  148. static int roles_cache_insert_object_nested(Avlnode **tree, role_object_nested *object);
  149. static int roles_cache_object_nested_from_dn(Slapi_DN *role_dn, role_object_nested **result);
  150. static int roles_cache_build_nsrole( caddr_t data, caddr_t arg );
  151. static int roles_cache_find_node( caddr_t d1, caddr_t d2 );
  152. static int roles_cache_find_roles_in_suffix(Slapi_DN *target_entry_dn, roles_cache_def **list_of_roles);
  153. static int roles_is_entry_member_of_object(caddr_t data, caddr_t arg );
  154. static int roles_is_entry_member_of_object_ext(vattr_context *c, caddr_t data, caddr_t arg );
  155. static int roles_check_managed(Slapi_Entry *entry_to_check, role_object *role, int *present);
  156. static int roles_check_filtered(vattr_context *c, Slapi_Entry *entry_to_check, role_object *role, int *present);
  157. static int roles_check_nested(caddr_t data, caddr_t arg);
  158. static int roles_is_inscope(Slapi_Entry *entry_to_check, Slapi_DN *role_dn);
  159. static void berval_set_string(struct berval *bv, const char* string);
  160. static void roles_cache_role_def_delete(roles_cache_def *role_def);
  161. static void roles_cache_role_def_free(roles_cache_def *role_def);
  162. static void roles_cache_role_object_free(role_object *this_role);
  163. static void roles_cache_role_object_nested_free(role_object_nested *this_role);
  164. static int roles_cache_dump( caddr_t data, caddr_t arg );
  165. static int roles_cache_add_entry_cb(Slapi_Entry* e, void *callback_data);
  166. static void roles_cache_result_cb( int rc, void *callback_data);
  167. static Slapi_DN* roles_cache_get_top_suffix(Slapi_DN *suffix);
  168. /* ============== FUNCTIONS ================ */
  169. /* roles_cache_init
  170. ----------------
  171. create the cache for all the existing suffixes
  172. starts up the threads which wait for changes
  173. also registers vattr callbacks
  174. return 0 if OK
  175. return -1 otherwise
  176. */
  177. int roles_cache_init()
  178. {
  179. int rc = 0;
  180. void *node = NULL;
  181. Slapi_DN *sdn = NULL;
  182. roles_cache_def *new_suffix = NULL;
  183. slapi_log_error(SLAPI_LOG_PLUGIN,
  184. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_init\n");
  185. if ( global_lock == NULL )
  186. {
  187. global_lock = PR_NewRWLock(0,"roles_cache");
  188. }
  189. /* grab the views interface */
  190. if(slapi_apib_get_interface(Views_v1_0_GUID, &views_api))
  191. {
  192. /* lets be tolerant if views is disabled */
  193. views_api = 0;
  194. }
  195. /* For each top suffix, get the roles definitions defined below it */
  196. PR_RWLock_Wlock(global_lock);
  197. sdn = slapi_get_first_suffix(&node, 0);
  198. while (sdn)
  199. {
  200. if ( (new_suffix = roles_cache_create_suffix(sdn)) == NULL )
  201. {
  202. PR_DestroyRWLock(global_lock);
  203. global_lock = NULL;
  204. return(-1);
  205. }
  206. if ( roles_cache_add_roles_from_suffix(sdn, new_suffix) != 0 )
  207. {
  208. /* No roles in that suffix, stop the thread and remove it ? */
  209. }
  210. sdn = slapi_get_next_suffix(&node, 0);
  211. }
  212. PR_RWLock_Unlock(global_lock);
  213. /* to expose roles_check to ACL plugin */
  214. slapi_register_role_check(roles_check);
  215. /* Register a callback on backends creation|modification|deletion,
  216. so that we update the corresponding cache */
  217. slapi_register_backend_state_change(NULL, roles_cache_trigger_update_suffix);
  218. if ( slapi_vattrspi_register((vattr_sp_handle **)&vattr_handle,
  219. roles_sp_get_value,
  220. roles_sp_compare_value,
  221. roles_sp_list_types) )
  222. {
  223. slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
  224. "roles_cache_init: slapi_vattrspi_register failed\n");
  225. PR_DestroyRWLock(global_lock);
  226. global_lock = NULL;
  227. return(-1);
  228. }
  229. else if ( slapi_vattrspi_regattr(vattr_handle,NSROLEATTR,"", NULL) )
  230. {
  231. slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
  232. "roles_cache_init: slapi_vattrspi_regattr failed\n");
  233. slapi_ch_free((void **)&vattr_handle);
  234. PR_DestroyRWLock(global_lock);
  235. global_lock = NULL;
  236. return(-1);
  237. }
  238. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_init\n");
  239. return rc;
  240. }
  241. /* roles_cache_create_suffix
  242. -------------------------
  243. Create a new entry in the global list
  244. return a pointer on the suffix stucture: OK
  245. return NULL: fail
  246. */
  247. static roles_cache_def *roles_cache_create_suffix(Slapi_DN *sdn)
  248. {
  249. roles_cache_def *current_suffix = NULL;
  250. roles_cache_def *new_suffix = NULL;
  251. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_create_suffix\n");
  252. /* Allocate a new suffix block */
  253. new_suffix = (roles_cache_def*)slapi_ch_calloc(1, sizeof(roles_cache_def));
  254. if ( new_suffix == NULL )
  255. {
  256. slapi_log_error(SLAPI_LOG_FATAL,
  257. ROLES_PLUGIN_SUBSYSTEM,
  258. "roles_cache_create_suffix: Unable to allocate memory, cannot create role cache\n");
  259. return(NULL);
  260. }
  261. new_suffix->cache_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "roles_def_lock");
  262. new_suffix->change_lock = slapi_new_mutex();
  263. new_suffix->stop_lock = slapi_new_mutex();
  264. new_suffix->create_lock = slapi_new_mutex();
  265. if ( new_suffix->stop_lock == NULL ||
  266. new_suffix->change_lock == NULL ||
  267. new_suffix->cache_lock == NULL ||
  268. new_suffix->create_lock == NULL )
  269. {
  270. slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
  271. "roles_cache_create_suffix: Lock creation failed\n");
  272. roles_cache_role_def_free(new_suffix);
  273. return(NULL);
  274. }
  275. new_suffix->something_changed = slapi_new_condvar(new_suffix->change_lock);
  276. if ( new_suffix->something_changed == NULL)
  277. {
  278. slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
  279. "roles_cache_create_suffix: Lock creation failed\n");
  280. roles_cache_role_def_free(new_suffix);
  281. return(NULL);
  282. }
  283. new_suffix->suffix_created = slapi_new_condvar(new_suffix->create_lock);
  284. if ( new_suffix->suffix_created == NULL)
  285. {
  286. slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
  287. "roles_cache_create_suffix: Lock creation failed\n");
  288. roles_cache_role_def_free(new_suffix);
  289. return(NULL);
  290. }
  291. new_suffix->keeprunning = 1;
  292. new_suffix->suffix_dn = slapi_sdn_dup(sdn);
  293. /* those 3 items are used to give back info to the thread when
  294. it is awakened */
  295. new_suffix->notified_dn = NULL;
  296. new_suffix->notified_entry = NULL;
  297. new_suffix->notified_operation = 0;
  298. /* Create the global list */
  299. if ( roles_list == NULL )
  300. {
  301. roles_list = new_suffix;
  302. }
  303. else
  304. {
  305. current_suffix = roles_list;
  306. while ( current_suffix != NULL )
  307. {
  308. if ( current_suffix->next == NULL )
  309. {
  310. current_suffix->next = new_suffix;
  311. break;
  312. }
  313. else
  314. {
  315. current_suffix = current_suffix->next;
  316. }
  317. }
  318. }
  319. /* to prevent deadlock */
  320. new_suffix->is_ready = 0;
  321. if ( (new_suffix->roles_tid = PR_CreateThread (PR_USER_THREAD,
  322. roles_cache_wait_on_change,
  323. (void*)new_suffix,
  324. PR_PRIORITY_NORMAL,
  325. PR_GLOBAL_THREAD,
  326. PR_UNJOINABLE_THREAD,
  327. SLAPD_DEFAULT_THREAD_STACKSIZE)) == NULL )
  328. {
  329. slapi_log_error( SLAPI_LOG_FATAL, ROLES_PLUGIN_SUBSYSTEM,
  330. "roles_cache_create_suffix: PR_CreateThread failed\n");
  331. roles_cache_role_def_delete(new_suffix);
  332. return(NULL);
  333. }
  334. slapi_lock_mutex(new_suffix->create_lock);
  335. if (new_suffix->is_ready != 1)
  336. {
  337. slapi_wait_condvar(new_suffix->suffix_created, NULL);
  338. }
  339. slapi_unlock_mutex(new_suffix->create_lock);
  340. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_create_suffix\n");
  341. return(new_suffix);
  342. }
  343. /* roles_cache_wait_on_change
  344. --------------------------
  345. Sit around waiting on a notification that something has
  346. changed, then fires off the updates
  347. */
  348. static void roles_cache_wait_on_change(void * arg)
  349. {
  350. roles_cache_def *roles_def = (roles_cache_def*)arg;
  351. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_wait_on_change\n");
  352. slapi_lock_mutex(roles_def->stop_lock);
  353. slapi_lock_mutex(roles_def->change_lock);
  354. while ( roles_def->keeprunning)
  355. {
  356. slapi_unlock_mutex(roles_def->change_lock);
  357. slapi_lock_mutex(roles_def->change_lock);
  358. /* means that the thread corresponding to that suffix is ready to receive notifications
  359. from the server */
  360. slapi_lock_mutex(roles_def->create_lock);
  361. if ( roles_def->is_ready == 0 )
  362. {
  363. slapi_notify_condvar( roles_def->suffix_created, 1 );
  364. roles_def->is_ready = 1;
  365. }
  366. slapi_unlock_mutex(roles_def->create_lock);
  367. /* XXX In case the BE containing this role_def signaled
  368. a shut down between the unlock/lock above should
  369. test roles_def->keeprunning before
  370. going to sleep.
  371. */
  372. slapi_wait_condvar(roles_def->something_changed, NULL);
  373. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "roles_cache_wait_on_change \n");
  374. if ( roles_def->keeprunning )
  375. {
  376. roles_cache_update(roles_def);
  377. }
  378. }
  379. /* shut down the cache */
  380. slapi_unlock_mutex(roles_def->change_lock);
  381. slapi_unlock_mutex(roles_def->stop_lock);
  382. roles_cache_role_def_free(roles_def);
  383. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_wait_on_change thread exit\n");
  384. }
  385. /* roles_cache_trigger_update_suffix
  386. --------------------------------
  387. This is called when a backend changes state (created|modified|deleted)
  388. We simply signal to update the associated role cache in this case
  389. */
  390. static void roles_cache_trigger_update_suffix(void *handle, char *be_name, int old_be_state, int new_be_state)
  391. {
  392. roles_cache_def *current_role = roles_list;
  393. const Slapi_DN *be_suffix_dn = NULL;
  394. Slapi_DN *top_suffix_dn = NULL;
  395. Slapi_Backend *backend = NULL;
  396. int found = 0;
  397. PR_RWLock_Wlock(global_lock);
  398. if ( (new_be_state == SLAPI_BE_STATE_DELETE) || (new_be_state == SLAPI_BE_STATE_OFFLINE) )
  399. {
  400. /* Invalidate and rebuild the whole cache */
  401. roles_cache_def *current_role = NULL;
  402. roles_cache_def *next_role = NULL;
  403. Slapi_DN *sdn = NULL;
  404. void *node = NULL;
  405. roles_cache_def *new_suffix = NULL;
  406. /* Go through all the roles list and trigger the associated structure */
  407. current_role = roles_list;
  408. while ( current_role )
  409. {
  410. slapi_lock_mutex(current_role->change_lock);
  411. current_role->keeprunning = 0;
  412. next_role = current_role->next;
  413. slapi_notify_condvar(current_role->something_changed, 1 );
  414. slapi_unlock_mutex(current_role->change_lock);
  415. current_role = next_role;
  416. }
  417. /* rebuild a new one */
  418. roles_list = NULL;
  419. sdn = slapi_get_first_suffix(&node, 0);
  420. while (sdn)
  421. {
  422. if ( (new_suffix = roles_cache_create_suffix(sdn)) == NULL )
  423. {
  424. PR_RWLock_Unlock(global_lock);
  425. return;
  426. }
  427. roles_cache_add_roles_from_suffix(sdn, new_suffix);
  428. sdn = slapi_get_next_suffix(&node, 0);
  429. }
  430. PR_RWLock_Unlock(global_lock);
  431. return;
  432. }
  433. /* Backend back on line or new one created*/
  434. backend = slapi_be_select_by_instance_name(be_name);
  435. if ( backend != NULL )
  436. {
  437. be_suffix_dn = slapi_be_getsuffix(backend, 0);
  438. top_suffix_dn = roles_cache_get_top_suffix((Slapi_DN *)be_suffix_dn);
  439. }
  440. while ( (current_role != NULL) && !found && (top_suffix_dn != NULL) )
  441. {
  442. /* The backend already exists (back online): so invalidate "old roles definitions" */
  443. if ( slapi_sdn_compare(current_role->suffix_dn, top_suffix_dn) == 0 )
  444. {
  445. roles_cache_role_def_delete(current_role);
  446. found = 1;
  447. }
  448. else
  449. {
  450. current_role = current_role->next;
  451. }
  452. }
  453. if ( top_suffix_dn != NULL )
  454. {
  455. /* Add the new definitions in the cache */
  456. roles_cache_def *new_suffix = roles_cache_create_suffix(top_suffix_dn);
  457. if ( new_suffix != NULL )
  458. {
  459. roles_cache_add_roles_from_suffix(top_suffix_dn, new_suffix);
  460. }
  461. slapi_sdn_free(&top_suffix_dn);
  462. }
  463. PR_RWLock_Unlock(global_lock);
  464. }
  465. /* roles_cache_trigger_update_role
  466. --------------------------------
  467. Call when an entry containing a role definition has been added, modified
  468. or deleted
  469. */
  470. static void roles_cache_trigger_update_role(char *dn, Slapi_Entry *roles_entry, Slapi_DN *be_dn, int operation)
  471. {
  472. int found = 0;
  473. roles_cache_def *current_role = NULL;
  474. PR_RWLock_Wlock(global_lock);
  475. current_role = roles_list;
  476. slapi_log_error( SLAPI_LOG_PLUGIN,
  477. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_trigger_update_role: %x \n", roles_list);
  478. /* Go through all the roles list and trigger the associated structure */
  479. /* be_dn is already the top suffix for that dn */
  480. while ( (current_role != NULL) && !found )
  481. {
  482. if ( slapi_sdn_compare(current_role->suffix_dn, be_dn) == 0 )
  483. {
  484. found = 1;
  485. }
  486. else
  487. {
  488. current_role = current_role->next;
  489. }
  490. }
  491. if ( found )
  492. {
  493. slapi_lock_mutex(current_role->change_lock);
  494. slapi_entry_free (current_role->notified_entry);
  495. current_role->notified_entry = roles_entry;
  496. slapi_ch_free ((void**)&(current_role->notified_dn));
  497. current_role->notified_dn = dn;
  498. current_role->notified_operation = operation;
  499. roles_cache_update(current_role);
  500. slapi_unlock_mutex(current_role->change_lock);
  501. }
  502. PR_RWLock_Unlock(global_lock);
  503. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_trigger_update_role: %x \n", roles_list);
  504. }
  505. /* roles_cache_update
  506. ------------------
  507. Update the cache associated to a suffix
  508. Return 0: ok
  509. Return -1: fail
  510. */
  511. static int roles_cache_update(roles_cache_def *suffix_to_update)
  512. {
  513. int rc = 0;
  514. int operation;
  515. Slapi_Entry *entry = NULL;
  516. Slapi_DN *dn = NULL;
  517. role_object *to_delete = NULL;
  518. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_update \n");
  519. PR_RWLock_Wlock(suffix_to_update->cache_lock);
  520. operation = suffix_to_update->notified_operation;
  521. entry = suffix_to_update->notified_entry;
  522. dn = slapi_sdn_new();
  523. slapi_sdn_set_dn_byval(dn, suffix_to_update->notified_dn);
  524. if ( (entry != NULL) && (dn != NULL) )
  525. {
  526. if ( (operation == SLAPI_OPERATION_MODIFY) ||
  527. (operation == SLAPI_OPERATION_DELETE) )
  528. {
  529. /* delete it */
  530. int dummy;
  531. to_delete = (role_object *)avl_delete(&(suffix_to_update->avl_tree), dn, roles_cache_find_node, &dummy);
  532. roles_cache_role_object_free(to_delete);
  533. to_delete = NULL;
  534. if ( slapi_is_loglevel_set(SLAPI_LOG_PLUGIN) )
  535. {
  536. avl_apply(suffix_to_update->avl_tree, (IFP)roles_cache_dump, &rc, -1, AVL_INORDER);
  537. }
  538. }
  539. if ( (operation == SLAPI_OPERATION_MODIFY) ||
  540. (operation ==SLAPI_OPERATION_ADD) )
  541. {
  542. rc = roles_cache_create_role_under(&suffix_to_update,entry);
  543. }
  544. if ( entry != NULL )
  545. {
  546. slapi_entry_free(entry);
  547. }
  548. suffix_to_update->notified_entry = NULL;
  549. }
  550. PR_RWLock_Unlock(suffix_to_update->cache_lock);
  551. if ( dn != NULL )
  552. {
  553. slapi_sdn_free(&dn);
  554. }
  555. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_update \n");
  556. return(rc);
  557. }
  558. /* roles_cache_stop
  559. ----------------
  560. XXX the stop_lock of a roles_cache_def
  561. doesn't seem to serve any useful purpose...
  562. */
  563. void roles_cache_stop()
  564. {
  565. roles_cache_def *current_role = NULL;
  566. roles_cache_def *next_role = NULL;
  567. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_stop\n");
  568. /* Go through all the roles list and trigger the associated structure */
  569. PR_RWLock_Wlock(global_lock);
  570. current_role = roles_list;
  571. while ( current_role )
  572. {
  573. slapi_lock_mutex(current_role->change_lock);
  574. current_role->keeprunning = 0;
  575. next_role = current_role->next;
  576. slapi_notify_condvar(current_role->something_changed, 1 );
  577. slapi_unlock_mutex(current_role->change_lock);
  578. current_role = next_role;
  579. }
  580. PR_RWLock_Unlock(global_lock);
  581. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_stop\n");
  582. }
  583. /* roles_cache_is_role_entry
  584. -------------------------
  585. Check if the entry is a role
  586. return -1: error in processing
  587. return 0: entry is not a role
  588. return 1: entry is a role
  589. */
  590. static int roles_cache_is_role_entry(struct slapi_entry *entry)
  591. {
  592. Slapi_Attr *pObjclasses = NULL;
  593. Slapi_Value *val = NULL;
  594. char *pObj = NULL;
  595. int index = 0;
  596. int nsroledefinition = 0;
  597. int nsrolesimpleOrComplex = 0;
  598. int nsroletype = 0;
  599. if ( entry == NULL )
  600. {
  601. return(0);
  602. }
  603. if ( slapi_entry_attr_find(entry, "objectclass", &pObjclasses) )
  604. {
  605. slapi_log_error( SLAPI_LOG_FATAL,
  606. ROLES_PLUGIN_SUBSYSTEM,
  607. "roles_cache_is_role_entry: failed to get objectclass from %s\n",slapi_entry_get_dn_const(entry));
  608. return(-1);
  609. }
  610. /* Check out the object classes to see if this was a nsroledefinition */
  611. val = 0;
  612. index = slapi_attr_first_value( pObjclasses, &val );
  613. while(val)
  614. {
  615. const char *p;
  616. int len = 0;
  617. pObj = (char*)slapi_value_get_string(val);
  618. for ( p = pObj, len = 0;
  619. (*p != '\0') && (*p != ' ');
  620. p++, len++ )
  621. {
  622. ; /* NULL */
  623. }
  624. if ( !strncasecmp(pObj, (char*)"nsroledefinition", len) )
  625. {
  626. nsroledefinition = 1;
  627. }
  628. if ( !strncasecmp(pObj, (char*)"nssimpleroledefinition", len) ||
  629. !strncasecmp(pObj, (char*)"nscomplexroledefinition", len) )
  630. {
  631. nsrolesimpleOrComplex = 1;
  632. }
  633. if( !strncasecmp(pObj, (char*)"nsmanagedroledefinition", len) ||
  634. !strncasecmp(pObj, (char*)"nsfilteredroledefinition", len) ||
  635. !strncasecmp(pObj, (char*)"nsnestedroledefinition", len)
  636. )
  637. {
  638. nsroletype = 1;
  639. }
  640. index = slapi_attr_next_value( pObjclasses, index, &val );
  641. }
  642. if ( (nsroledefinition == 0) ||
  643. (nsrolesimpleOrComplex == 0) ||
  644. (nsroletype == 0) )
  645. {
  646. return(0);
  647. }
  648. return(1);
  649. }
  650. /* roles_cache_change_notify
  651. -------------------------
  652. determines if the change effects the cache and if so
  653. signals a rebuild
  654. -- called when modify|modrdn|add|delete operation is performed --
  655. -- called from a postoperation on an entry
  656. XXX this implies that the client may have already received his LDAP response,
  657. but that there will be a delay before he sees the effect in the roles cache.
  658. Should we be doing this processing in a BE_POST_MODIFY postop
  659. which is called _before_ the response goes to the client ?
  660. */
  661. void roles_cache_change_notify(Slapi_PBlock *pb)
  662. {
  663. char *dn = NULL;
  664. struct slapi_entry *e = NULL;
  665. struct slapi_entry *pre = NULL;
  666. struct slapi_entry *entry = NULL;
  667. Slapi_Backend *be = NULL;
  668. Slapi_Operation *pb_operation = NULL;
  669. int operation;
  670. int do_update = 0;
  671. int rc = -1;
  672. slapi_log_error(SLAPI_LOG_PLUGIN,
  673. ROLES_PLUGIN_SUBSYSTEM,
  674. "--> roles_cache_change_notify\n");
  675. /* if the current operation has failed, don't even try the post operation */
  676. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &rc );
  677. if ( rc != LDAP_SUCCESS )
  678. {
  679. return;
  680. }
  681. /* Don't update local cache when remote entries are updated */
  682. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  683. if ( ( be!=NULL ) &&
  684. ( slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)) )
  685. {
  686. return;
  687. }
  688. slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
  689. if( dn == NULL )
  690. {
  691. return;
  692. }
  693. slapi_pblock_get (pb, SLAPI_OPERATION, &pb_operation);
  694. operation = operation_get_type(pb_operation);
  695. switch (operation)
  696. {
  697. case SLAPI_OPERATION_DELETE:
  698. slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
  699. if( e == NULL )
  700. {
  701. return;
  702. }
  703. break;
  704. case SLAPI_OPERATION_ADD:
  705. slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
  706. if ( e == NULL )
  707. {
  708. return;
  709. }
  710. break;
  711. case SLAPI_OPERATION_MODIFY:
  712. case SLAPI_OPERATION_MODRDN:
  713. /* those operations are treated the same way and modify is a deletion followed by an addition.
  714. the only point to take care is that dn is the olddn */
  715. operation = SLAPI_OPERATION_MODIFY;
  716. slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &pre);
  717. if( pre == NULL )
  718. {
  719. return;
  720. }
  721. slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
  722. if ( e == NULL )
  723. {
  724. return;
  725. }
  726. break;
  727. default:
  728. slapi_log_error( SLAPI_LOG_FATAL,
  729. ROLES_PLUGIN_SUBSYSTEM,
  730. "roles_cache_change_notify: unknown operation %d\n",operation);
  731. return;
  732. }
  733. if ( operation != SLAPI_OPERATION_MODIFY )
  734. {
  735. if ( roles_cache_is_role_entry(e) != 1 )
  736. {
  737. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_change_notify: not a role entry\n");
  738. return;
  739. }
  740. entry = slapi_entry_dup(e);
  741. do_update = 1;
  742. }
  743. else
  744. {
  745. int is_pre_role = roles_cache_is_role_entry(pre);
  746. int is_post_role = roles_cache_is_role_entry(e);
  747. if ( (is_pre_role==1) && (is_post_role==1) ) /* role definition has changed */
  748. {
  749. entry = slapi_entry_dup(e);
  750. do_update = 1;
  751. }
  752. else if ( is_pre_role == 1 ) /* entry is no more a role */
  753. {
  754. operation = SLAPI_OPERATION_DELETE;
  755. do_update = 1;
  756. }
  757. else if ( is_post_role == 1 ) /* entry is now a role */
  758. {
  759. operation = SLAPI_OPERATION_ADD;
  760. entry = slapi_entry_dup(e);
  761. do_update = 1;
  762. }
  763. else
  764. {
  765. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_change_notify: not a role entry\n");
  766. return;
  767. }
  768. }
  769. if ( do_update )
  770. {
  771. #ifdef moretrace
  772. if ( e != NULL )
  773. {
  774. Slapi_Attr *attr = NULL;
  775. int rc;
  776. /* Get the list of nested roles */
  777. rc = slapi_entry_attr_find(e,ROLE_NESTED_ATTR_NAME,&attr);
  778. if ( (rc == 0) && attr)
  779. {
  780. /* Recurse to get the definition objects for them */
  781. Slapi_Value **va = attr_get_present_values(attr);
  782. int i = 0;
  783. char *string = NULL;
  784. for ( i = 0; va[i] != NULL; i++ )
  785. {
  786. string = (char*)slapi_value_get_string(va[i]);
  787. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "roles_cache_change_notify:%s\n",string);
  788. }
  789. }
  790. }
  791. #endif
  792. Slapi_DN *top_suffix = roles_cache_get_top_suffix(*(be->be_suffix));
  793. if ( top_suffix != NULL )
  794. {
  795. roles_cache_trigger_update_role( slapi_ch_strdup(dn), entry,
  796. top_suffix,
  797. operation);
  798. slapi_sdn_free(&top_suffix);
  799. }
  800. }
  801. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_change_notify\n");
  802. }
  803. /* roles_cache_get_top_suffix
  804. -------------------------
  805. The returned Slapi_DN must be freed with slapi_sdn_free().
  806. */
  807. static Slapi_DN* roles_cache_get_top_suffix(Slapi_DN *suffix)
  808. {
  809. Slapi_DN *current_suffix = NULL;
  810. Slapi_DN parent_suffix;
  811. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_get_top_suffix\n");
  812. if ( suffix == NULL )
  813. {
  814. return(NULL);
  815. }
  816. current_suffix = slapi_sdn_new();
  817. slapi_sdn_init(&parent_suffix);
  818. /* we must get the top suffix for that DN */
  819. slapi_sdn_copy(suffix,current_suffix);
  820. while ( !slapi_sdn_isempty(current_suffix) )
  821. {
  822. if ( slapi_is_root_suffix(current_suffix) != 1 )
  823. {
  824. slapi_sdn_get_parent(current_suffix,&parent_suffix);
  825. slapi_sdn_copy(&parent_suffix, current_suffix);
  826. }
  827. else
  828. {
  829. slapi_sdn_done(&parent_suffix);
  830. return(current_suffix);
  831. }
  832. }
  833. /* we should not return that way ... */
  834. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_get_top_suffix\n");
  835. slapi_sdn_done(&parent_suffix);
  836. slapi_sdn_free(&current_suffix);
  837. return(NULL);
  838. }
  839. /* roles_cache_add_roles_from_suffix
  840. -------------------------------
  841. Get the roles entries under the suffix
  842. return 0: OK
  843. return -1: this suffix has no role defined
  844. */
  845. static int roles_cache_add_roles_from_suffix(Slapi_DN *suffix_dn, roles_cache_def *suffix_def)
  846. {
  847. /* Search subtree-level under this entry */
  848. int rc = -1;
  849. roles_cache_search_roles info;
  850. Slapi_PBlock *int_search_pb = NULL;
  851. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_add_roles_from_suffix\n");
  852. info.suffix_def = suffix_def;
  853. info.rc = LDAP_NO_SUCH_OBJECT;
  854. /* Get the roles definitions of the given suffix_dn */
  855. int_search_pb = slapi_pblock_new ();
  856. slapi_search_internal_set_pb(int_search_pb,
  857. (char*)slapi_sdn_get_ndn(suffix_dn),
  858. LDAP_SCOPE_SUBTREE,
  859. ROLE_DEFINITION_FILTER,
  860. allUserAttributes,
  861. 0 /* attrsonly */,
  862. NULL /* controls */,
  863. NULL /* uniqueid */,
  864. roles_get_plugin_identity(),
  865. SLAPI_OP_FLAG_NEVER_CHAIN /* actions : get local roles only */ );
  866. slapi_search_internal_callback_pb(int_search_pb,
  867. &info /* callback_data */,
  868. roles_cache_result_cb,
  869. roles_cache_add_entry_cb,
  870. NULL /* referral_callback */);
  871. slapi_pblock_destroy (int_search_pb);
  872. int_search_pb = NULL;
  873. if ( info.rc == LDAP_SUCCESS )
  874. {
  875. rc = 0;
  876. }
  877. slapi_log_error( SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_add_roles_from_suffix\n");
  878. return(rc);
  879. }
  880. /* roles_cache_add_entry_cb
  881. -----------------------
  882. */
  883. static int roles_cache_add_entry_cb(Slapi_Entry* e, void *callback_data)
  884. {
  885. roles_cache_search_roles *info=(roles_cache_search_roles *)callback_data;
  886. roles_cache_def *suffix = info->suffix_def;
  887. roles_cache_create_role_under(&suffix, e);
  888. return(0);
  889. }
  890. /* roles_cache_result_cb
  891. -----------------------
  892. */
  893. static void roles_cache_result_cb( int rc, void *callback_data) {
  894. roles_cache_search_roles *info=(roles_cache_search_roles *)callback_data;
  895. info->rc = rc;
  896. }
  897. /* roles_cache_create_role_under
  898. ----------------------------
  899. Create the avl tree of roles definitions defined in the scope
  900. of the suffix
  901. Return 0: OK
  902. Return -1: fail
  903. */
  904. static int roles_cache_create_role_under(roles_cache_def** roles_cache_suffix, Slapi_Entry *entry)
  905. {
  906. int rc;
  907. role_object *new_role = NULL;
  908. slapi_log_error(SLAPI_LOG_PLUGIN,
  909. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_create_role_under: %s - %x\n",
  910. slapi_sdn_get_dn((*roles_cache_suffix)->suffix_dn),
  911. (*roles_cache_suffix)->avl_tree);
  912. rc = roles_cache_create_object_from_entry(entry,&new_role,0);
  913. slapi_log_error(SLAPI_LOG_PLUGIN,
  914. ROLES_PLUGIN_SUBSYSTEM,
  915. "roles_cache_create_role_under: create node for entry %s - rc: %d SUFFIX: %x\n",
  916. slapi_entry_get_dn_const(entry), rc, (*roles_cache_suffix)->avl_tree);
  917. if ( (rc == 0) && new_role)
  918. {
  919. /* Add to the tree where avl_data is a role_object struct */
  920. rc = roles_cache_insert_object(&((*roles_cache_suffix)->avl_tree),new_role);
  921. slapi_log_error(SLAPI_LOG_PLUGIN,
  922. ROLES_PLUGIN_SUBSYSTEM, "roles_cache_create_role_under:%s in tree %x rc: %d\n",
  923. (char*)slapi_sdn_get_ndn(new_role->dn),
  924. (*roles_cache_suffix)->avl_tree, rc);
  925. }
  926. return(rc);
  927. }
  928. /* roles_cache_create_object_from_entry
  929. ------------------------------------
  930. Create a node role_object from the information contained in role_entry
  931. Return 0
  932. Return ENOMEM: fail
  933. Return SLAPI_ROLE_DEFINITION_ERROR: fail
  934. Return SLAPI_ROLE_ERROR_NO_FILTER_SPECIFIED: fail
  935. Return SLAPI_ROLE_ERROR_FILTER_BAD: fail
  936. */
  937. static int roles_cache_create_object_from_entry(Slapi_Entry *role_entry, role_object **result, int hint)
  938. {
  939. int rc = 0;
  940. int type = 0;
  941. role_object *this_role = NULL;
  942. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  943. "--> roles_cache_create_object_from_entry\n");
  944. *result = NULL;
  945. /* Do not allow circular dependencies */
  946. if ( hint > MAX_NESTED_ROLES )
  947. {
  948. char *ndn = NULL;
  949. ndn = slapi_entry_get_ndn( role_entry );
  950. slapi_log_error(
  951. SLAPI_LOG_FATAL,
  952. ROLES_PLUGIN_SUBSYSTEM,
  953. "Maximum roles nesting exceeded (%d), not retrieving roles from entry %s--probable circular definition\n",
  954. MAX_NESTED_ROLES,
  955. ndn);
  956. return (0);
  957. }
  958. /* Create the role cache definition */
  959. this_role = (role_object*)slapi_ch_calloc(1, sizeof(role_object));
  960. if (this_role == NULL )
  961. {
  962. return ENOMEM;
  963. }
  964. /* Check the entry is OK */
  965. /* Determine role type and assign to structure */
  966. /* We determine the role type by reading the objectclass */
  967. if ( roles_cache_is_role_entry(role_entry) == 0 )
  968. {
  969. /* Bad type */
  970. slapi_ch_free((void**)&this_role);
  971. return SLAPI_ROLE_DEFINITION_ERROR;
  972. }
  973. type = roles_cache_determine_class(role_entry);
  974. if (type != 0)
  975. {
  976. this_role->type = type;
  977. }
  978. else
  979. {
  980. /* Bad type */
  981. slapi_ch_free((void**)&this_role);
  982. return SLAPI_ROLE_DEFINITION_ERROR;
  983. }
  984. this_role->dn = slapi_sdn_new();
  985. slapi_sdn_copy(slapi_entry_get_sdn(role_entry),this_role->dn);
  986. /* Depending upon role type, pull out the remaining information we need */
  987. switch (this_role->type)
  988. {
  989. case ROLE_TYPE_MANAGED:
  990. /* Nothing further needed */
  991. break;
  992. case ROLE_TYPE_FILTERED:
  993. {
  994. Slapi_Filter *filter = NULL;
  995. char *filter_attr_value = NULL;
  996. /* Get the filter and retrieve the filter attribute */
  997. filter_attr_value = slapi_entry_attr_get_charptr(role_entry,ROLE_FILTER_ATTR_NAME);
  998. if ( filter_attr_value == NULL )
  999. {
  1000. /* Means probably no attribute or no value there */
  1001. slapi_ch_free((void**)&this_role);
  1002. return SLAPI_ROLE_ERROR_NO_FILTER_SPECIFIED;
  1003. }
  1004. /* Turn it into a slapi filter object */
  1005. filter = slapi_str2filter(filter_attr_value);
  1006. slapi_ch_free((void**)&filter_attr_value);
  1007. if ( filter == NULL )
  1008. {
  1009. /* An error has occured */
  1010. slapi_ch_free((void**)&this_role);
  1011. return SLAPI_ROLE_ERROR_FILTER_BAD;
  1012. }
  1013. /* Store on the object */
  1014. this_role->filter = filter;
  1015. break;
  1016. }
  1017. case ROLE_TYPE_NESTED:
  1018. {
  1019. Slapi_Attr *attr = NULL;
  1020. /* Get the list of nested roles */
  1021. rc = slapi_entry_attr_find(role_entry,ROLE_NESTED_ATTR_NAME,&attr);
  1022. if ( (rc == 0) && attr)
  1023. {
  1024. /* Recurse to get the definition objects for them */
  1025. Slapi_Value **va = attr_get_present_values(attr);
  1026. int i = 0;
  1027. char *string = NULL;
  1028. Slapi_DN nested_role_dn;
  1029. role_object_nested *nested_role_object = NULL;
  1030. for ( i = 0; va[i] != NULL; i++ )
  1031. {
  1032. string = (char*)slapi_value_get_string(va[i]);
  1033. /* Make a DN from the string */
  1034. slapi_sdn_init_dn_byref(&nested_role_dn,string);
  1035. slapi_log_error(SLAPI_LOG_PLUGIN,
  1036. ROLES_PLUGIN_SUBSYSTEM, "roles_cache_create_object_from_entry: dn %s, nested %s\n",
  1037. (char*)slapi_sdn_get_ndn(this_role->dn),string);
  1038. /* Make a role object nested from the DN */
  1039. rc = roles_cache_object_nested_from_dn(&nested_role_dn,&nested_role_object);
  1040. /* Insert it into the nested list */
  1041. if ( (rc == 0) && nested_role_object)
  1042. {
  1043. /* Add to the tree where avl_data is a role_object_nested struct */
  1044. rc = roles_cache_insert_object_nested(&(this_role->avl_tree),nested_role_object);
  1045. }
  1046. slapi_sdn_done(&nested_role_dn);
  1047. }
  1048. }
  1049. break;
  1050. }
  1051. default:
  1052. slapi_log_error(SLAPI_LOG_FATAL,
  1053. ROLES_PLUGIN_SUBSYSTEM, "wrong role type\n");
  1054. }
  1055. if ( rc == 0 )
  1056. {
  1057. *result = this_role;
  1058. }
  1059. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1060. "<-- roles_cache_create_object_from_entry\n");
  1061. return rc;
  1062. }
  1063. /* roles_cache_determine_class:
  1064. ----------------------------
  1065. Determine the type of role depending on the objectclass
  1066. Return the type of the role
  1067. */
  1068. static int roles_cache_determine_class(Slapi_Entry *role_entry)
  1069. {
  1070. /* Examine the entry's objectclass attribute */
  1071. int found_managed = 0;
  1072. int found_filtered = 0;
  1073. int found_nested = 0;
  1074. Slapi_Attr *attr= NULL;
  1075. struct berval bv = {0};
  1076. int rc = 0;
  1077. int type = 0;
  1078. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1079. "--> roles_cache_determine_class\n");
  1080. rc = slapi_entry_attr_find(role_entry,"objectclass",&attr);
  1081. if ( rc != 0 )
  1082. {
  1083. /* No objectclass, definitely an error */
  1084. return 0;
  1085. }
  1086. berval_set_string(&bv,ROLE_OBJECTCLASS_MANAGED);
  1087. rc = slapi_attr_value_find(attr,&bv);
  1088. if ( rc == 0 )
  1089. {
  1090. found_managed = 1;
  1091. type = ROLE_TYPE_MANAGED;
  1092. }
  1093. berval_set_string(&bv,ROLE_OBJECTCLASS_FILTERED);
  1094. rc = slapi_attr_value_find(attr,&bv);
  1095. if ( rc == 0 )
  1096. {
  1097. found_filtered = 1;
  1098. type = ROLE_TYPE_FILTERED;
  1099. }
  1100. berval_set_string(&bv,ROLE_OBJECTCLASS_NESTED);
  1101. rc = slapi_attr_value_find(attr,&bv);
  1102. if ( rc == 0 )
  1103. {
  1104. found_nested = 1;
  1105. type = ROLE_TYPE_NESTED;
  1106. }
  1107. if ( (found_managed + found_nested + found_filtered) > 1 )
  1108. {
  1109. /* Means some goofball configured a role definition which is trying to be more than one different type. error. */
  1110. return 0;
  1111. }
  1112. if ( (found_managed + found_nested + found_filtered) == 0)
  1113. {
  1114. /* Means this entry isn't any of the role types we handle. error. */
  1115. return 0;
  1116. }
  1117. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1118. "<-- roles_cache_determine_class\n");
  1119. /* Return the appropriate type ordinal */
  1120. return type;
  1121. }
  1122. /* roles_cache_node_cmp:
  1123. ---------------------
  1124. Comparison function to add a new node in the avl tree (avl_data is of type role_object)
  1125. */
  1126. static int roles_cache_node_cmp( caddr_t d1, caddr_t d2 )
  1127. {
  1128. role_object *role_to_insert = (role_object*)d1;
  1129. role_object *current_role = (role_object*)d2;
  1130. /* role_to_insert and current_role are never NULL in that context */
  1131. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1132. "roles_cache_node_cmp\n");
  1133. return (slapi_sdn_compare((Slapi_DN *)role_to_insert->dn, (Slapi_DN *)current_role->dn));
  1134. }
  1135. /* roles_cache_insert_object:
  1136. --------------------------
  1137. Insert a new node in the avl tree of a specific suffix
  1138. */
  1139. static int roles_cache_insert_object(Avlnode **tree, role_object *object)
  1140. {
  1141. slapi_log_error(SLAPI_LOG_PLUGIN,
  1142. ROLES_PLUGIN_SUBSYSTEM, "roles_cache_insert_object: %s in tree %x\n",
  1143. (char*)slapi_sdn_get_ndn(object->dn),
  1144. *tree);
  1145. return (avl_insert(tree, (caddr_t)object, roles_cache_node_cmp, avl_dup_error));
  1146. }
  1147. /* roles_cache_node_nested_cmp:
  1148. ----------------------------
  1149. Comparison function to add a new node in the avl tree
  1150. */
  1151. static int roles_cache_node_nested_cmp( caddr_t d1, caddr_t d2 )
  1152. {
  1153. role_object_nested *role_to_insert = (role_object_nested*)d1;
  1154. role_object_nested *current_role = (role_object_nested*)d2;
  1155. /* role_to_insert and current_role are never NULL in that context */
  1156. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1157. "roles_cache_node_nested_cmp\n");
  1158. return slapi_sdn_compare(role_to_insert->dn, current_role->dn);
  1159. }
  1160. /* roles_cache_insert_object_nested:
  1161. ---------------------------------
  1162. Insert a new node in the avl tree of a specific suffix
  1163. */
  1164. static int roles_cache_insert_object_nested(Avlnode **tree, role_object_nested *object)
  1165. {
  1166. slapi_log_error(SLAPI_LOG_PLUGIN,
  1167. ROLES_PLUGIN_SUBSYSTEM, "roles_cache_insert_object_nested: %s in tree %x: \n",
  1168. (char*)slapi_sdn_get_ndn(object->dn), *tree);
  1169. return (avl_insert(tree, (caddr_t)object, roles_cache_node_nested_cmp, avl_dup_error));
  1170. }
  1171. /* roles_cache_object_nested_from_dn
  1172. ----------------------------------
  1173. Get the role associated to an entry DN
  1174. Return 0: OK
  1175. Return ENOMEM: fail
  1176. */
  1177. static int roles_cache_object_nested_from_dn(Slapi_DN *role_dn, role_object_nested **result)
  1178. {
  1179. role_object_nested *nested_role = NULL;
  1180. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1181. "--> roles_cache_object_nested_from_dn\n");
  1182. *result = NULL;
  1183. /* Create the role cache definition */
  1184. nested_role = (role_object_nested*)slapi_ch_calloc(1, sizeof(role_object_nested));
  1185. if (nested_role == NULL )
  1186. {
  1187. return ENOMEM;
  1188. }
  1189. nested_role->dn = slapi_sdn_new();
  1190. slapi_sdn_copy(role_dn,nested_role->dn);
  1191. *result = nested_role;
  1192. slapi_log_error(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM,
  1193. "<-- roles_cache_object_nested_from_dn\n");
  1194. return 0;
  1195. }
  1196. /* roles_cache_listroles
  1197. --------------------
  1198. Lists all the roles an entry posesses
  1199. return_values = 0 means that we don't need the nsrole values
  1200. return_values = 1 means that we need the nsrole values
  1201. Return 0: the entry has nsrole
  1202. Return -1: the entry has no nsrole
  1203. */
  1204. int roles_cache_listroles(Slapi_Entry *entry, int return_values, Slapi_ValueSet **valueset_out)
  1205. {
  1206. return roles_cache_listroles_ext(NULL, entry, return_values, valueset_out);
  1207. }
  1208. int roles_cache_listroles_ext(vattr_context *c, Slapi_Entry *entry, int return_values, Slapi_ValueSet **valueset_out)
  1209. {
  1210. roles_cache_def *roles_cache = NULL;
  1211. int rc = 0;
  1212. roles_cache_build_result arg;
  1213. Slapi_Backend *backend = NULL;
  1214. slapi_log_error(SLAPI_LOG_PLUGIN,
  1215. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_listroles\n");
  1216. backend = slapi_mapping_tree_find_backend_for_sdn(slapi_entry_get_sdn(entry));
  1217. if ( (backend != NULL) && slapi_be_is_flag_set(backend,SLAPI_BE_FLAG_REMOTE_DATA) )
  1218. {
  1219. /* the entry is not local, so don't return anything */
  1220. return (-1);
  1221. }
  1222. if ( return_values )
  1223. {
  1224. *valueset_out = (Slapi_ValueSet*)slapi_ch_calloc(1,sizeof(Slapi_ValueSet));
  1225. slapi_valueset_init(*valueset_out);
  1226. }
  1227. /* First get a list of all the in-scope roles */
  1228. /* XXX really need a mutex for this read operation ? */
  1229. PR_RWLock_Rlock(global_lock);
  1230. rc = roles_cache_find_roles_in_suffix( slapi_entry_get_sdn(entry),&roles_cache);
  1231. PR_RWLock_Unlock(global_lock);
  1232. /* Traverse the tree checking if the entry has any of the roles */
  1233. if ( roles_cache != NULL )
  1234. {
  1235. if ( roles_cache->avl_tree )
  1236. {
  1237. arg.nsrole_values = valueset_out;
  1238. arg.need_value = return_values;
  1239. arg.requested_entry = entry;
  1240. arg.has_value = 0;
  1241. arg.context = c;
  1242. /* XXX really need a mutex for this read operation ? */
  1243. PR_RWLock_Rlock(roles_cache->cache_lock);
  1244. avl_apply(roles_cache->avl_tree, (IFP)roles_cache_build_nsrole, &arg, -1, AVL_INORDER);
  1245. PR_RWLock_Unlock(roles_cache->cache_lock);
  1246. if( !arg.has_value )
  1247. {
  1248. if ( return_values )
  1249. {
  1250. slapi_valueset_free(*valueset_out);
  1251. *valueset_out = NULL;
  1252. }
  1253. rc = -1;
  1254. }
  1255. /* Free the list (we already did that) */
  1256. }
  1257. else
  1258. {
  1259. if ( return_values )
  1260. {
  1261. slapi_valueset_free(*valueset_out);
  1262. *valueset_out = NULL;
  1263. }
  1264. rc = -1;
  1265. }
  1266. }
  1267. else
  1268. {
  1269. /* no roles associated */
  1270. rc = -1;
  1271. }
  1272. slapi_log_error(SLAPI_LOG_PLUGIN,
  1273. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_listroles\n");
  1274. return rc;
  1275. }
  1276. /* roles_cache_build_nsrole
  1277. ------------------------
  1278. Traverse the tree containing roles definitions for a suffix and for each
  1279. one of them, check wether the entry is a member of it or not
  1280. For ones which check out positive, we add their DN to the value
  1281. always return 0 to allow to trverse all the tree
  1282. */
  1283. static int roles_cache_build_nsrole( caddr_t data, caddr_t arg )
  1284. {
  1285. Slapi_Value *value = NULL;
  1286. roles_cache_build_result *result = (roles_cache_build_result*)arg;
  1287. role_object *this_role = (role_object*)data;
  1288. roles_cache_search_in_nested get_nsrole;
  1289. /* Return a value different from the stop flag to be able
  1290. to go through all the tree */
  1291. int rc = 0;
  1292. int tmprc = 0;
  1293. slapi_log_error(SLAPI_LOG_PLUGIN,
  1294. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_build_nsrole: role %s\n",
  1295. (char*) slapi_sdn_get_ndn(this_role->dn));
  1296. value = slapi_value_new_string("");
  1297. get_nsrole.is_entry_member_of = result->requested_entry;
  1298. get_nsrole.present = 0;
  1299. get_nsrole.hint = 0;
  1300. tmprc = roles_is_entry_member_of_object_ext(result->context, (caddr_t)this_role, (caddr_t)&get_nsrole);
  1301. if (SLAPI_VIRTUALATTRS_LOOP_DETECTED == tmprc)
  1302. {
  1303. /* all we want to detect and return is loop/stack overflow */
  1304. rc = tmprc;
  1305. }
  1306. /* If so, add its DN to the attribute */
  1307. if (get_nsrole.present)
  1308. {
  1309. result->has_value = 1;
  1310. if ( result->need_value )
  1311. {
  1312. slapi_value_set_string(value,(char*) slapi_sdn_get_ndn(this_role->dn));
  1313. slapi_valueset_add_value(*(result->nsrole_values),value);
  1314. }
  1315. else
  1316. {
  1317. /* we don't need the value but we already know there is one nsrole.
  1318. stop the traversal
  1319. */
  1320. rc = -1;
  1321. }
  1322. }
  1323. slapi_value_free(&value);
  1324. slapi_log_error(SLAPI_LOG_PLUGIN,
  1325. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_build_nsrole\n");
  1326. return rc;
  1327. }
  1328. /* roles_check
  1329. -----------
  1330. Checks if an entry has a presented role, assuming that we've already verified
  1331. that
  1332. the role both exists and is in scope
  1333. return 0: no processing error
  1334. return -1: error
  1335. */
  1336. int roles_check(Slapi_Entry *entry_to_check, Slapi_DN *role_dn, int *present)
  1337. {
  1338. roles_cache_def *roles_cache = NULL;
  1339. role_object *this_role = NULL;
  1340. roles_cache_search_in_nested get_nsrole;
  1341. int rc = 0;
  1342. slapi_log_error(SLAPI_LOG_PLUGIN,
  1343. ROLES_PLUGIN_SUBSYSTEM, "--> roles_check\n");
  1344. *present = 0;
  1345. PR_RWLock_Rlock(global_lock);
  1346. if ( roles_cache_find_roles_in_suffix(slapi_entry_get_sdn(entry_to_check),
  1347. &roles_cache) != 0 )
  1348. {
  1349. PR_RWLock_Unlock(global_lock);
  1350. return -1;
  1351. }
  1352. PR_RWLock_Unlock(global_lock);
  1353. this_role = (role_object *)avl_find(roles_cache->avl_tree, role_dn, (IFP)roles_cache_find_node);
  1354. /* MAB: For some reason the assumption made by this function (the role exists and is in scope)
  1355. * does not seem to be true... this_role might be NULL after the avl_find call (is the avl_tree
  1356. * broken? Anyway, this is crashing the 5.1 server on 29-Aug-01, so I am applying the following patch
  1357. * to avoid the crash inside roles_is_entry_member_of_object */
  1358. /* Begin patch */
  1359. if (!this_role) {
  1360. /* Assume that the entry is not member of the role (*present=0) and leave... */
  1361. return rc;
  1362. }
  1363. /* End patch */
  1364. get_nsrole.is_entry_member_of = entry_to_check;
  1365. get_nsrole.present = 0;
  1366. get_nsrole.hint = 0;
  1367. roles_is_entry_member_of_object((caddr_t)this_role, (caddr_t)&get_nsrole);
  1368. *present = get_nsrole.present;
  1369. slapi_log_error(SLAPI_LOG_PLUGIN,
  1370. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_check\n");
  1371. return rc;
  1372. }
  1373. /* roles_cache_find_node:
  1374. ---------------------
  1375. Comparison function to add a new node in the avl tree
  1376. */
  1377. static int roles_cache_find_node( caddr_t d1, caddr_t d2 )
  1378. {
  1379. Slapi_DN *data = (Slapi_DN *)d1;
  1380. role_object *role= (role_object *)d2;
  1381. /* role is not NULL in that context */
  1382. slapi_log_error(SLAPI_LOG_PLUGIN,
  1383. ROLES_PLUGIN_SUBSYSTEM, "roles_cache_find_node: %s %s\n",
  1384. slapi_sdn_get_dn(data), slapi_sdn_get_dn(role->dn));
  1385. return (slapi_sdn_compare(data, (Slapi_DN *)role->dn));
  1386. }
  1387. /* roles_cache_find_roles_in_suffix
  1388. -------------------------------
  1389. Find all the roles in scope to an entry
  1390. */
  1391. static int roles_cache_find_roles_in_suffix(Slapi_DN *target_entry_dn, roles_cache_def **list_of_roles)
  1392. {
  1393. int rc = -1;
  1394. Slapi_Backend *backend = NULL;
  1395. slapi_log_error(SLAPI_LOG_PLUGIN,
  1396. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_find_roles_in_suffix\n");
  1397. *list_of_roles = NULL;
  1398. backend = slapi_mapping_tree_find_backend_for_sdn(target_entry_dn);
  1399. if ( (backend != NULL) && !slapi_be_is_flag_set(backend,SLAPI_BE_FLAG_REMOTE_DATA) )
  1400. {
  1401. Slapi_DN *suffix = roles_cache_get_top_suffix(*(backend->be_suffix));
  1402. roles_cache_def *current_role = roles_list;
  1403. /* Go through all the roles list and trigger the associated structure */
  1404. while ( (current_role != NULL) && (suffix != NULL) )
  1405. {
  1406. if ( slapi_sdn_compare(current_role->suffix_dn, suffix) == 0 )
  1407. {
  1408. *list_of_roles = current_role;
  1409. /* OK, we have found one */
  1410. slapi_sdn_free(&suffix);
  1411. return 0;
  1412. }
  1413. else
  1414. {
  1415. current_role = current_role->next;
  1416. }
  1417. }
  1418. if ( suffix != NULL )
  1419. {
  1420. slapi_sdn_free(&suffix);
  1421. }
  1422. /* If we got out that way, means that we didn't have find
  1423. roles definitions for that suffix */
  1424. return rc;
  1425. }
  1426. slapi_log_error(SLAPI_LOG_PLUGIN,
  1427. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_find_roles_in_suffix\n");
  1428. return rc;
  1429. }
  1430. /* roles_is_entry_member_of_object
  1431. --------------------------------
  1432. Check if the entry is part of a role defined in its suffix
  1433. return 0: ok
  1434. return 1: fail
  1435. -> to check the presence, see present
  1436. */
  1437. static int roles_is_entry_member_of_object(caddr_t data, caddr_t argument )
  1438. {
  1439. return roles_is_entry_member_of_object_ext(NULL, data, argument );
  1440. }
  1441. static int roles_is_entry_member_of_object_ext(vattr_context *c, caddr_t data, caddr_t argument )
  1442. {
  1443. int rc = -1;
  1444. roles_cache_search_in_nested *get_nsrole = (roles_cache_search_in_nested*)argument;
  1445. role_object *this_role = (role_object*)data;
  1446. Slapi_Entry *entry_to_check = get_nsrole->is_entry_member_of;
  1447. slapi_log_error(SLAPI_LOG_PLUGIN,
  1448. ROLES_PLUGIN_SUBSYSTEM, "--> roles_is_entry_member_of_object\n");
  1449. if (!roles_is_inscope(entry_to_check, this_role->dn))
  1450. {
  1451. slapi_log_error(SLAPI_LOG_PLUGIN,
  1452. ROLES_PLUGIN_SUBSYSTEM, "roles_is_entry_member_of_object-> entry not in scope of role\n");
  1453. return rc;
  1454. }
  1455. if ( this_role != NULL )
  1456. {
  1457. /* Determine the role type */
  1458. switch (this_role->type)
  1459. {
  1460. case ROLE_TYPE_MANAGED:
  1461. rc = roles_check_managed(entry_to_check,this_role,&get_nsrole->present);
  1462. break;
  1463. case ROLE_TYPE_FILTERED:
  1464. rc = roles_check_filtered(c, entry_to_check,this_role,&get_nsrole->present);
  1465. break;
  1466. case ROLE_TYPE_NESTED:
  1467. {
  1468. /* Go through the tree of the nested DNs */
  1469. get_nsrole->hint++;
  1470. avl_apply(this_role->avl_tree, (IFP)roles_check_nested, get_nsrole, 0, AVL_INORDER);
  1471. get_nsrole->hint--;
  1472. /* kexcoff?? */
  1473. rc = get_nsrole->present;
  1474. break;
  1475. }
  1476. default:
  1477. slapi_log_error(SLAPI_LOG_FATAL,
  1478. ROLES_PLUGIN_SUBSYSTEM, "roles_is_entry_member_of_object-> invalid role type\n");
  1479. }
  1480. }
  1481. slapi_log_error(SLAPI_LOG_PLUGIN,
  1482. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_is_entry_member_of_object\n");
  1483. return rc;
  1484. }
  1485. /* roles_check_managed
  1486. -------------------------
  1487. Check a managed role: we just need to check the content of the entry's nsRoleDN attribute
  1488. against the role DN
  1489. return 0: ok
  1490. return 1: fail
  1491. -> to check the presence, see present
  1492. */
  1493. static int roles_check_managed(Slapi_Entry *entry_to_check, role_object *role, int *present)
  1494. {
  1495. int rc = 0;
  1496. Slapi_Attr *attr = NULL;
  1497. slapi_log_error(SLAPI_LOG_PLUGIN,
  1498. ROLES_PLUGIN_SUBSYSTEM, "--> roles_check_managed\n");
  1499. /* Get the attribute */
  1500. rc = slapi_entry_attr_find(entry_to_check,ROLE_MANAGED_ATTR_NAME,&attr);
  1501. if ( rc == 0)
  1502. {
  1503. struct berval bv = {0};
  1504. char *dn_string = NULL;
  1505. /* Check content against the presented DN */
  1506. /* We assume that this function handles normalization and so on */
  1507. dn_string = (char*) slapi_sdn_get_ndn(role->dn);
  1508. berval_set_string(&bv,dn_string);
  1509. rc = slapi_attr_value_find(attr,&bv);
  1510. if ( rc == 0 )
  1511. {
  1512. *present = 1;
  1513. }
  1514. }
  1515. slapi_log_error(SLAPI_LOG_PLUGIN,
  1516. ROLES_PLUGIN_SUBSYSTEM,
  1517. "<-- roles_check_managed: entry %s role %s present %d\n",
  1518. slapi_entry_get_dn_const(entry_to_check),(char*)slapi_sdn_get_ndn(role->dn),*present);
  1519. return rc;
  1520. }
  1521. /* roles_check_filtered
  1522. --------------------------
  1523. Check a filtered role: call slapi_filter_test here on the entry
  1524. and the filter from the role object
  1525. return 0: ok
  1526. return 1: fail
  1527. -> to check the presence, see present
  1528. */
  1529. static int roles_check_filtered(vattr_context *c, Slapi_Entry *entry_to_check, role_object *role, int *present)
  1530. {
  1531. int rc = 0;
  1532. slapi_log_error(SLAPI_LOG_PLUGIN,
  1533. ROLES_PLUGIN_SUBSYSTEM, "--> roles_check_filtered\n");
  1534. rc = slapi_vattr_filter_test_ext(slapi_vattr_get_pblock_from_context(c),
  1535. entry_to_check, role->filter, 0, 0);
  1536. if ( rc == 0 )
  1537. {
  1538. *present = 1;
  1539. }
  1540. slapi_log_error(SLAPI_LOG_PLUGIN,
  1541. ROLES_PLUGIN_SUBSYSTEM,
  1542. "<-- roles_check_filtered: entry %s role %s present %d\n",
  1543. slapi_entry_get_dn_const(entry_to_check),(char*)slapi_sdn_get_ndn(role->dn),*present);
  1544. return rc;
  1545. }
  1546. /* roles_check_nested
  1547. ------------------------
  1548. Check a nested role
  1549. return 0: ok
  1550. return -1: fail
  1551. -> to check the presence, see present
  1552. */
  1553. static int roles_check_nested(caddr_t data, caddr_t arg)
  1554. {
  1555. roles_cache_search_in_nested *get_nsrole = (roles_cache_search_in_nested*)arg;
  1556. int rc = -1;
  1557. role_object_nested *current_nested_role = (role_object_nested*)data;
  1558. /* do not allow circular dependencies, the cheap and easy way */
  1559. if( get_nsrole->hint > MAX_NESTED_ROLES)
  1560. {
  1561. char *ndn = NULL;
  1562. ndn = slapi_entry_get_ndn( get_nsrole->is_entry_member_of );
  1563. slapi_log_error(SLAPI_LOG_FATAL,
  1564. ROLES_PLUGIN_SUBSYSTEM,
  1565. "Maximum roles nesting exceeded (max %d current %d), not checking roles in entry %s--probable circular definition\n",
  1566. MAX_NESTED_ROLES,
  1567. get_nsrole->hint,
  1568. ndn);
  1569. /* Stop traversal value */
  1570. return 0;
  1571. }
  1572. /* Here we traverse the list of nested roles, calling the appropriate
  1573. evaluation function for those in turn */
  1574. if (current_nested_role)
  1575. {
  1576. roles_cache_def *roles_cache = NULL;
  1577. role_object *this_role = NULL;
  1578. slapi_log_error(SLAPI_LOG_PLUGIN,
  1579. ROLES_PLUGIN_SUBSYSTEM,
  1580. "-->roles_check_nested: entry %s role %s present %d\n",
  1581. slapi_entry_get_dn_const(get_nsrole->is_entry_member_of),
  1582. (char*)slapi_sdn_get_ndn(current_nested_role->dn),
  1583. get_nsrole->present);
  1584. if ( roles_cache_find_roles_in_suffix(current_nested_role->dn,
  1585. &roles_cache) != 0 )
  1586. {
  1587. return rc;
  1588. }
  1589. if ( slapi_is_loglevel_set(SLAPI_LOG_PLUGIN) )
  1590. {
  1591. avl_apply(roles_cache->avl_tree, (IFP)roles_cache_dump, &rc, -1, AVL_INORDER);
  1592. }
  1593. this_role = (role_object *)avl_find(roles_cache->avl_tree,
  1594. current_nested_role->dn,
  1595. (IFP)roles_cache_find_node);
  1596. if ( this_role == NULL )
  1597. {
  1598. /* the nested role doesn't exist */
  1599. slapi_log_error(SLAPI_LOG_FATAL,
  1600. ROLES_PLUGIN_SUBSYSTEM,
  1601. "The nested role %s doesn't exist\n",
  1602. (char*)slapi_sdn_get_ndn(current_nested_role->dn));
  1603. return rc;
  1604. }
  1605. /* get the role_object data associated to that dn */
  1606. if ( roles_is_inscope(get_nsrole->is_entry_member_of, this_role->dn) )
  1607. {
  1608. /* The list of nested roles is contained in the role definition */
  1609. roles_is_entry_member_of_object((caddr_t)this_role, (caddr_t)get_nsrole);
  1610. if ( get_nsrole->present == 1 )
  1611. {
  1612. return 0;
  1613. }
  1614. }
  1615. }
  1616. slapi_log_error(SLAPI_LOG_PLUGIN,
  1617. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_check_nested\n");
  1618. return rc;
  1619. }
  1620. /* roles_is_inscope
  1621. ----------------------
  1622. Tells us if a presented role is in scope with respect to the presented entry
  1623. */
  1624. static int roles_is_inscope(Slapi_Entry *entry_to_check, Slapi_DN *role_dn)
  1625. {
  1626. int rc;
  1627. Slapi_DN role_parent;
  1628. slapi_log_error(SLAPI_LOG_PLUGIN,
  1629. ROLES_PLUGIN_SUBSYSTEM, "--> roles_is_inscope\n");
  1630. slapi_sdn_init(&role_parent);
  1631. slapi_sdn_get_parent(role_dn,&role_parent);
  1632. rc = slapi_sdn_scope_test(slapi_entry_get_sdn( entry_to_check ),
  1633. &role_parent,
  1634. LDAP_SCOPE_SUBTREE);
  1635. /* we need to check whether the entry would be returned by a view in scope */
  1636. if(!rc && views_api)
  1637. {
  1638. rc = views_entry_exists(views_api, (char*)slapi_sdn_get_ndn(&role_parent), entry_to_check);
  1639. }
  1640. slapi_sdn_done(&role_parent);
  1641. slapi_log_error(SLAPI_LOG_PLUGIN,
  1642. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_is_inscope: entry %s role %s result %d\n",
  1643. slapi_entry_get_dn_const(entry_to_check),(char*)slapi_sdn_get_ndn(role_dn), rc);
  1644. return (rc);
  1645. }
  1646. static void berval_set_string(struct berval *bv, const char* string)
  1647. {
  1648. bv->bv_len= strlen(string);
  1649. bv->bv_val= (void*)string; /* We cast away the const, but we're not going to change anything
  1650. */
  1651. }
  1652. /* roles_cache_role_def_delete
  1653. ----------------------------
  1654. */
  1655. static void roles_cache_role_def_delete(roles_cache_def *role_def)
  1656. {
  1657. roles_cache_def *current = roles_list;
  1658. roles_cache_def *previous = NULL;
  1659. slapi_log_error(SLAPI_LOG_PLUGIN,
  1660. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_def_delete\n");
  1661. while ( current!= NULL )
  1662. {
  1663. if ( slapi_sdn_compare(current->suffix_dn, role_def->suffix_dn) == 0 )
  1664. {
  1665. if ( previous== NULL )
  1666. {
  1667. roles_list = current->next;
  1668. }
  1669. else
  1670. {
  1671. previous->next = current->next;
  1672. }
  1673. slapi_lock_mutex(role_def->change_lock);
  1674. role_def->keeprunning = 0;
  1675. slapi_notify_condvar(role_def->something_changed, 1 );
  1676. slapi_unlock_mutex(role_def->change_lock);
  1677. break;
  1678. }
  1679. else
  1680. {
  1681. previous = current;
  1682. current = current->next;
  1683. }
  1684. }
  1685. slapi_log_error(SLAPI_LOG_PLUGIN,
  1686. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_def_delete\n");
  1687. }
  1688. /* roles_cache_role_def_free
  1689. ----------------------------
  1690. */
  1691. static void roles_cache_role_def_free(roles_cache_def *role_def)
  1692. {
  1693. slapi_log_error(SLAPI_LOG_PLUGIN,
  1694. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_def_free\n");
  1695. if ( role_def == NULL )
  1696. {
  1697. return;
  1698. }
  1699. slapi_lock_mutex(role_def->stop_lock);
  1700. avl_free(role_def->avl_tree, (IFP)roles_cache_role_object_free);
  1701. slapi_sdn_free(&(role_def->suffix_dn));
  1702. PR_DestroyRWLock(role_def->cache_lock);
  1703. role_def->cache_lock = NULL;
  1704. slapi_destroy_mutex(role_def->change_lock);
  1705. role_def->change_lock = NULL;
  1706. slapi_destroy_condvar(role_def->something_changed);
  1707. slapi_destroy_mutex(role_def->create_lock);
  1708. role_def->create_lock = NULL;
  1709. slapi_destroy_condvar(role_def->suffix_created);
  1710. slapi_ch_free((void**)&role_def->notified_dn);
  1711. if ( role_def->notified_entry != NULL )
  1712. {
  1713. slapi_entry_free(role_def->notified_entry);
  1714. }
  1715. slapi_unlock_mutex(role_def->stop_lock);
  1716. slapi_destroy_mutex(role_def->stop_lock);
  1717. role_def->stop_lock = NULL;
  1718. slapi_ch_free((void**)&role_def);
  1719. slapi_log_error(SLAPI_LOG_PLUGIN,
  1720. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_def_free\n");
  1721. }
  1722. /* roles_cache_role_object_free
  1723. ----------------------------
  1724. */
  1725. static void roles_cache_role_object_free(role_object *this_role)
  1726. {
  1727. slapi_log_error(SLAPI_LOG_PLUGIN,
  1728. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_object_free\n");
  1729. if ( this_role == NULL )
  1730. {
  1731. return;
  1732. }
  1733. switch (this_role->type)
  1734. {
  1735. case ROLE_TYPE_MANAGED:
  1736. /* Nothing further needed */
  1737. break;
  1738. case ROLE_TYPE_FILTERED:
  1739. /* Free the filter */
  1740. if (this_role->filter)
  1741. {
  1742. slapi_filter_free(this_role->filter,1);
  1743. this_role->filter = NULL;
  1744. }
  1745. break;
  1746. case ROLE_TYPE_NESTED:
  1747. /* Free the list of nested roles */
  1748. {
  1749. avl_free(this_role->avl_tree, roles_cache_role_object_nested_free);
  1750. }
  1751. break;
  1752. }
  1753. slapi_sdn_free(&this_role->dn);
  1754. /* Free the object */
  1755. slapi_ch_free((void**)&this_role);
  1756. slapi_log_error(SLAPI_LOG_PLUGIN,
  1757. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_object_free\n");
  1758. }
  1759. /* roles_cache_role_object_nested_free
  1760. ------------------------------------
  1761. */
  1762. static void roles_cache_role_object_nested_free(role_object_nested *this_role)
  1763. {
  1764. slapi_log_error(SLAPI_LOG_PLUGIN,
  1765. ROLES_PLUGIN_SUBSYSTEM, "--> roles_cache_role_object_nested_free\n");
  1766. if ( this_role == NULL )
  1767. {
  1768. return;
  1769. }
  1770. slapi_sdn_free(&this_role->dn);
  1771. /* Free the object */
  1772. slapi_ch_free((void**)&this_role);
  1773. slapi_log_error(SLAPI_LOG_PLUGIN,
  1774. ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_role_object_nested_free\n");
  1775. }
  1776. static int roles_cache_dump( caddr_t data, caddr_t arg )
  1777. {
  1778. role_object *this_role = (role_object*)data;
  1779. slapi_log_error(SLAPI_LOG_PLUGIN,
  1780. ROLES_PLUGIN_SUBSYSTEM, "roles_cache_dump: %x - %s - %x\n",
  1781. this_role, (char*)slapi_sdn_get_ndn(this_role->dn), this_role->avl_tree);
  1782. return 0;
  1783. }