roles_cache.c 62 KB

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