acl_ext.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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. #include "acl.h"
  39. static void acl__done_aclpb ( struct acl_pblock *aclpb );
  40. static void acl__dump_stats ( struct acl_pblock *aclpb , const char *block_type);
  41. static Acl_PBlock * acl__get_aclpb_from_pool ( );
  42. static int acl__put_aclpb_back_to_pool ( Acl_PBlock *aclpb );
  43. static Acl_PBlock * acl__malloc_aclpb ( );
  44. static char * acl__get_aclpb_type ( Acl_PBlock *aclpb );
  45. static PRLock *aclext_get_lock ();
  46. struct acl_pbqueue {
  47. Acl_PBlock *aclq_free;
  48. Acl_PBlock *aclq_busy;
  49. short aclq_nfree;
  50. short aclq_nbusy;
  51. PRLock *aclq_lock;
  52. };
  53. typedef struct acl_pbqueue Acl_PBqueue;
  54. static Acl_PBqueue *aclQueue;
  55. /* structure with information for each extension */
  56. typedef struct acl_ext
  57. {
  58. char *object_name; /* name of the object extended */
  59. int object_type; /* handle to the extended object */
  60. int handle; /* extension handle */
  61. } acl_ext;
  62. static acl_ext acl_ext_list [ACL_EXT_ALL];
  63. /*
  64. * EXTENSION INITIALIZATION, CONSTRUCTION, & DESTRUCTION
  65. *
  66. */
  67. int
  68. acl_init_ext ()
  69. {
  70. int rc;
  71. acl_ext_list[ACL_EXT_OPERATION].object_name = SLAPI_EXT_OPERATION;
  72. rc = slapi_register_object_extension(plugin_name, SLAPI_EXT_OPERATION,
  73. acl_operation_ext_constructor,
  74. acl_operation_ext_destructor,
  75. &acl_ext_list[ACL_EXT_OPERATION].object_type,
  76. &acl_ext_list[ACL_EXT_OPERATION].handle);
  77. if ( rc != 0 ) return rc;
  78. acl_ext_list[ACL_EXT_CONNECTION].object_name = SLAPI_EXT_CONNECTION;
  79. rc = slapi_register_object_extension(plugin_name, SLAPI_EXT_CONNECTION,
  80. acl_conn_ext_constructor,
  81. acl_conn_ext_destructor,
  82. &acl_ext_list[ACL_EXT_CONNECTION].object_type,
  83. &acl_ext_list[ACL_EXT_CONNECTION].handle);
  84. return rc;
  85. }
  86. /* Interface to get the extensions */
  87. void *
  88. acl_get_ext (ext_type type, void *object)
  89. {
  90. struct acl_ext ext;
  91. void *data;
  92. if ( type >= ACL_EXT_ALL ) {
  93. slapi_log_error ( SLAPI_LOG_ACL, plugin_name,
  94. "Invalid extension type:%d\n", type );
  95. return NULL;
  96. }
  97. /* find the requested extension */
  98. ext = acl_ext_list [type];
  99. data = slapi_get_object_extension(ext.object_type, object, ext.handle);
  100. return data;
  101. }
  102. void
  103. acl_set_ext (ext_type type, void *object, void *data)
  104. {
  105. if ( type >= 0 && type < ACL_EXT_ALL )
  106. {
  107. struct acl_ext ext = acl_ext_list [type];
  108. slapi_set_object_extension ( ext.object_type, object, ext.handle, data );
  109. }
  110. }
  111. /****************************************************************************
  112. * Global lock array so that private extension between connection and operation
  113. * co-exist
  114. *
  115. ******************************************************************************/
  116. struct ext_lockArray {
  117. PRLock **lockArray;
  118. int numlocks;
  119. };
  120. static struct ext_lockArray extLockArray;
  121. /* PKBxxx: make this a configurable. Start with 2 * maxThreads */
  122. #define ACLEXT_MAX_LOCKS 40
  123. int
  124. aclext_alloc_lockarray ( )
  125. {
  126. int i;
  127. PRLock *lock;
  128. extLockArray.lockArray =
  129. (PRLock **) slapi_ch_calloc ( ACLEXT_MAX_LOCKS, sizeof ( PRLock *) );
  130. for ( i =0; i < ACLEXT_MAX_LOCKS; i++) {
  131. if (NULL == (lock = PR_NewLock()) ) {
  132. slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
  133. "Unable to allocate locks used for private extension\n");
  134. return 1;
  135. }
  136. extLockArray.lockArray[i] = lock;
  137. }
  138. extLockArray.numlocks = ACLEXT_MAX_LOCKS;
  139. return 0;
  140. }
  141. static PRUint32 slot_id =0;
  142. static PRLock *
  143. aclext_get_lock ()
  144. {
  145. PRUint16 slot = slot_id % ACLEXT_MAX_LOCKS;
  146. slot_id++;
  147. return ( extLockArray.lockArray[slot] );
  148. }
  149. /****************************************************************************/
  150. /* CONNECTION EXTENSION SPECIFIC */
  151. /****************************************************************************/
  152. void *
  153. acl_conn_ext_constructor ( void *object, void *parent )
  154. {
  155. struct acl_cblock *ext = NULL;
  156. ext = (struct acl_cblock * ) slapi_ch_calloc (1, sizeof (struct acl_cblock ) );
  157. if (( ext->aclcb_lock = aclext_get_lock () ) == NULL ) {
  158. slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
  159. "Unable to get Read/Write lock for CONNECTION extension\n");
  160. slapi_ch_free ( (void **) &ext );
  161. return NULL;
  162. }
  163. ext->aclcb_sdn = slapi_sdn_new ();
  164. /* store the signatures */
  165. ext->aclcb_aclsignature = acl_get_aclsignature();
  166. ext->aclcb_state = -1;
  167. return ext;
  168. }
  169. void
  170. acl_conn_ext_destructor ( void *ext, void *object, void *parent )
  171. {
  172. struct acl_cblock *aclcb = ext;
  173. PRLock *shared_lock;
  174. if ( NULL == aclcb ) return;
  175. PR_Lock ( aclcb->aclcb_lock );
  176. shared_lock = aclcb->aclcb_lock;
  177. acl_clean_aclEval_context ( &aclcb->aclcb_eval_context, 0 /* clean*/ );
  178. slapi_sdn_free ( &aclcb->aclcb_sdn );
  179. aclcb->aclcb_lock = NULL;
  180. slapi_ch_free ( (void **) &aclcb );
  181. PR_Unlock ( shared_lock );
  182. }
  183. /****************************************************************************/
  184. /* OPERATION EXTENSION SPECIFIC */
  185. /****************************************************************************/
  186. void *
  187. acl_operation_ext_constructor ( void *object, void *parent )
  188. {
  189. Acl_PBlock *aclpb = NULL;
  190. TNF_PROBE_0_DEBUG(acl_operation_ext_constructor_start ,"ACL","");
  191. /* This means internal operations */
  192. if ( NULL == parent) {
  193. TNF_PROBE_1_DEBUG(acl_operation_ext_constructor_end ,"ACL","",
  194. tnf_string,internal_op,"");
  195. return NULL;
  196. }
  197. aclpb = acl__get_aclpb_from_pool();
  198. if ( NULL == aclpb ) {
  199. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  200. "Operation extension allocation Failed\n");
  201. }
  202. TNF_PROBE_0_DEBUG(acl_operation_ext_constructor_end ,"ACL","");
  203. return aclpb;
  204. }
  205. void
  206. acl_operation_ext_destructor ( void *ext, void *object, void *parent )
  207. {
  208. struct acl_cblock *aclcb = NULL;
  209. struct acl_pblock *aclpb = NULL;
  210. TNF_PROBE_0_DEBUG(acl_operation_ext_destructor_start ,"ACL","");
  211. if ( (NULL == parent ) || (NULL == ext)) {
  212. TNF_PROBE_1_DEBUG(acl_operation_ext_destructor_end ,"ACL","",
  213. tnf_string,internal_op,"");
  214. return;
  215. }
  216. aclpb = (Acl_PBlock *) ext;
  217. if ( (NULL == aclpb) ||
  218. (NULL == aclpb->aclpb_pblock) ||
  219. (!(aclpb->aclpb_state & ACLPB_INITIALIZED)))
  220. goto clean_aclpb;
  221. /* get the connection extension */
  222. aclcb = (struct acl_cblock *) acl_get_ext ( ACL_EXT_CONNECTION, parent );
  223. /* We are about to get out of this connection. Move all the
  224. ** cached information to the acl private block which hangs
  225. ** from the connection struct.
  226. */
  227. if ( aclcb && aclcb->aclcb_lock &&
  228. ( (aclpb->aclpb_state & ACLPB_UPD_ACLCB_CACHE ) ||
  229. (aclpb->aclpb_state & ACLPB_INCR_ACLCB_CACHE ) ) ) {
  230. aclEvalContext *c_evalContext;
  231. int attr_only = 0;
  232. PRLock *shared_lock = aclcb->aclcb_lock;
  233. if (aclcb->aclcb_lock ) PR_Lock ( shared_lock );
  234. else {
  235. goto clean_aclpb;
  236. }
  237. if ( !aclcb->aclcb_lock ) {
  238. slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "aclcb lock released! aclcb cache can't be refreshed\n");
  239. PR_Unlock ( shared_lock );
  240. goto clean_aclpb;
  241. }
  242. /* We need to refresh the aclcb cache */
  243. if ( aclpb->aclpb_state & ACLPB_UPD_ACLCB_CACHE )
  244. acl_clean_aclEval_context ( &aclcb->aclcb_eval_context, 0 /* clean*/ );
  245. if ( aclpb->aclpb_prev_entryEval_context.acle_numof_attrs ) {
  246. c_evalContext = &aclpb->aclpb_prev_entryEval_context;
  247. } else {
  248. c_evalContext = &aclpb->aclpb_curr_entryEval_context;
  249. }
  250. if (( aclpb->aclpb_state & ACLPB_INCR_ACLCB_CACHE ) &&
  251. ! ( aclpb->aclpb_state & ACLPB_UPD_ACLCB_CACHE ))
  252. attr_only = 1;
  253. acl_copyEval_context ( NULL, c_evalContext, &aclcb->aclcb_eval_context, attr_only );
  254. aclcb->aclcb_aclsignature = aclpb->aclpb_signature;
  255. if ( aclcb->aclcb_sdn && aclpb->aclpb_authorization_sdn &&
  256. (0 != slapi_sdn_compare ( aclcb->aclcb_sdn,
  257. aclpb->aclpb_authorization_sdn ) ) ) {
  258. slapi_sdn_set_ndn_byval( aclcb->aclcb_sdn,
  259. slapi_sdn_get_ndn ( aclpb->aclpb_authorization_sdn ) );
  260. }
  261. aclcb->aclcb_state = 0;
  262. aclcb->aclcb_state |= ACLCB_HAS_CACHED_EVALCONTEXT;
  263. PR_Unlock ( shared_lock );
  264. }
  265. clean_aclpb:
  266. if ( aclpb ) {
  267. if ( aclpb->aclpb_proxy ) {
  268. TNF_PROBE_0_DEBUG(acl_proxy_aclpbdoneback_start ,"ACL","");
  269. acl__done_aclpb( aclpb->aclpb_proxy );
  270. /* Put back to the Pool */
  271. acl__put_aclpb_back_to_pool ( aclpb->aclpb_proxy );
  272. aclpb->aclpb_proxy = NULL;
  273. TNF_PROBE_0_DEBUG(acl_proxy_aclpbdoneback_end ,"ACL","");
  274. }
  275. TNF_PROBE_0_DEBUG(acl_aclpbdoneback_start ,"ACL","");
  276. acl__done_aclpb( aclpb);
  277. acl__put_aclpb_back_to_pool ( aclpb );
  278. TNF_PROBE_0_DEBUG(acl_aclpbdoneback_end ,"ACL","");
  279. }
  280. TNF_PROBE_0_DEBUG(acl_operation_ext_destructor_end ,"ACL","");
  281. }
  282. /****************************************************************************/
  283. /* FUNCTIONS TO MANAGE THE ACLPB POOL */
  284. /****************************************************************************/
  285. /*
  286. * Get the right acl pblock
  287. */
  288. struct acl_pblock *
  289. acl_get_aclpb ( Slapi_PBlock *pb, int type )
  290. {
  291. Acl_PBlock *aclpb = NULL;
  292. void *op = NULL;
  293. slapi_pblock_get ( pb, SLAPI_OPERATION, &op );
  294. aclpb = (Acl_PBlock *) acl_get_ext ( ACL_EXT_OPERATION, op );
  295. if (NULL == aclpb ) return NULL;
  296. if ( type == ACLPB_BINDDN_PBLOCK )
  297. return aclpb;
  298. else if ( type == ACLPB_PROXYDN_PBLOCK )
  299. return aclpb->aclpb_proxy;
  300. else
  301. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  302. "acl_get_aclpb: Invalid aclpb type %d\n", type );
  303. return NULL;
  304. }
  305. /*
  306. * Create a new proxy acl pblock
  307. *
  308. */
  309. struct acl_pblock *
  310. acl_new_proxy_aclpb( Slapi_PBlock *pb )
  311. {
  312. void *op;
  313. Acl_PBlock *aclpb = NULL;
  314. Acl_PBlock *proxy_aclpb = NULL;
  315. slapi_pblock_get ( pb, SLAPI_OPERATION, &op );
  316. aclpb = (Acl_PBlock *) acl_get_ext ( ACL_EXT_OPERATION, op );
  317. if (NULL == aclpb ) return NULL;
  318. proxy_aclpb = acl__get_aclpb_from_pool();
  319. if (NULL == proxy_aclpb) return NULL;
  320. proxy_aclpb->aclpb_type = ACLPB_TYPE_PROXY;
  321. aclpb->aclpb_proxy = proxy_aclpb;
  322. return proxy_aclpb;
  323. }
  324. static int
  325. acl__handle_config_entry (Slapi_Entry *e, void *callback_data )
  326. {
  327. *(int * )callback_data = slapi_entry_attr_get_int( e, "nsslapd-threadnumber");
  328. return 0;
  329. }
  330. /*
  331. * Create a pool of acl pblock. Created during the ACL plugin
  332. * initialization.
  333. */
  334. int
  335. acl_create_aclpb_pool ()
  336. {
  337. Acl_PBlock *aclpb;
  338. Acl_PBlock *prev_aclpb;
  339. Acl_PBlock *first_aclpb;
  340. int i;
  341. int maxThreads= 0;
  342. slapi_search_internal_callback( "cn=config", LDAP_SCOPE_BASE, "(objectclass=*)",
  343. NULL, 0 /* attrsonly */,
  344. &maxThreads/* callback_data */,
  345. NULL /* controls */,
  346. NULL /* result_callback */,
  347. acl__handle_config_entry,
  348. NULL /* referral_callback */);
  349. /* Create a pool pf aclpb */
  350. maxThreads = 2 * maxThreads;
  351. aclQueue = ( Acl_PBqueue *) slapi_ch_calloc ( 1, sizeof (Acl_PBqueue) );
  352. aclQueue->aclq_lock = PR_NewLock();
  353. if ( NULL == aclQueue->aclq_lock ) {
  354. /* ERROR */
  355. return 1;
  356. }
  357. prev_aclpb = NULL;
  358. first_aclpb = NULL;
  359. for ( i = 0; i < maxThreads; i++ ) {
  360. aclpb = acl__malloc_aclpb ();
  361. if ( 0 == i) first_aclpb = aclpb;
  362. aclpb->aclpb_prev = prev_aclpb;
  363. if ( prev_aclpb ) prev_aclpb->aclpb_next = aclpb;
  364. prev_aclpb = aclpb;
  365. }
  366. /* Since this is the begining, everybody is in free list */
  367. aclQueue->aclq_free = first_aclpb;
  368. aclQueue->aclq_nfree = maxThreads;
  369. return 0;
  370. }
  371. /*
  372. * Get a FREE acl pblock from the pool.
  373. *
  374. */
  375. static Acl_PBlock *
  376. acl__get_aclpb_from_pool ( )
  377. {
  378. Acl_PBlock *aclpb = NULL;
  379. Acl_PBlock *t_aclpb = NULL;
  380. PR_Lock (aclQueue->aclq_lock );
  381. /* Get the first aclpb from the FREE List */
  382. aclpb = aclQueue->aclq_free;
  383. if ( aclpb ) {
  384. t_aclpb = aclpb->aclpb_next;
  385. if ( t_aclpb ) t_aclpb->aclpb_prev = NULL;
  386. aclQueue->aclq_free = t_aclpb;
  387. /* make the this an orphon */
  388. aclpb->aclpb_prev = aclpb->aclpb_next = NULL;
  389. aclQueue->aclq_nfree--;
  390. } else {
  391. slapi_log_error ( SLAPI_LOG_ACL, plugin_name,
  392. "Unable to find a free aclpb\n");
  393. aclpb = acl__malloc_aclpb ();
  394. }
  395. /* Now move it to the FRONT of busy list */
  396. t_aclpb = aclQueue->aclq_busy;
  397. aclpb->aclpb_next = t_aclpb;
  398. if ( t_aclpb ) t_aclpb->aclpb_prev = aclpb;
  399. aclQueue->aclq_busy = aclpb;
  400. aclQueue->aclq_nbusy++;
  401. PR_Unlock (aclQueue->aclq_lock );
  402. return aclpb;
  403. }
  404. /*
  405. * Put the acl pblock into the FREE pool.
  406. *
  407. */
  408. static int
  409. acl__put_aclpb_back_to_pool ( Acl_PBlock *aclpb )
  410. {
  411. Acl_PBlock *p_aclpb, *n_aclpb;
  412. PR_Lock (aclQueue->aclq_lock );
  413. /* Remove it from the busy list */
  414. n_aclpb = aclpb->aclpb_next;
  415. p_aclpb = aclpb->aclpb_prev;
  416. if ( p_aclpb ) {
  417. p_aclpb->aclpb_next = n_aclpb;
  418. if ( n_aclpb ) n_aclpb->aclpb_prev = p_aclpb;
  419. } else {
  420. aclQueue->aclq_busy = n_aclpb;
  421. if ( n_aclpb ) n_aclpb->aclpb_prev = NULL;
  422. }
  423. aclQueue->aclq_nbusy--;
  424. /* Put back to the FREE list */
  425. aclpb->aclpb_prev = NULL;
  426. n_aclpb = aclQueue->aclq_free;
  427. aclpb->aclpb_next = n_aclpb;
  428. if ( n_aclpb ) n_aclpb->aclpb_prev = aclpb;
  429. aclQueue->aclq_free = aclpb;
  430. aclQueue->aclq_nfree++;
  431. PR_Unlock (aclQueue->aclq_lock );
  432. return 0;
  433. }
  434. /*
  435. * Allocate the basic acl pb
  436. *
  437. */
  438. static Acl_PBlock *
  439. acl__malloc_aclpb ( )
  440. {
  441. Acl_PBlock *aclpb = NULL;
  442. aclpb = ( Acl_PBlock *) slapi_ch_calloc ( 1, sizeof ( Acl_PBlock) );
  443. /* Now set the propert we need for ACL evaluations */
  444. if ((aclpb->aclpb_proplist = PListNew(NULL)) == NULL) {
  445. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  446. "Unable to allocate the aclprop PList\n");
  447. return NULL;
  448. }
  449. if (PListInitProp(aclpb->aclpb_proplist, 0, DS_PROP_ACLPB, aclpb, 0) < 0) {
  450. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  451. "Unable to set the ACL PBLOCK in the Plist\n");
  452. return NULL;
  453. }
  454. if (PListInitProp(aclpb->aclpb_proplist, 0, DS_ATTR_USERDN, aclpb, 0) < 0) {
  455. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  456. "Unable to set the USER DN in the Plist\n");
  457. return NULL;
  458. }
  459. if (PListInitProp(aclpb->aclpb_proplist, 0, DS_ATTR_AUTHTYPE, aclpb, 0) < 0) {
  460. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  461. "Unable to set the AUTH TYPE in the Plist\n");
  462. return NULL;
  463. }
  464. if (PListInitProp(aclpb->aclpb_proplist, 0, DS_ATTR_ENTRY, aclpb, 0) < 0) {
  465. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  466. "Unable to set the ENTRY TYPE in the Plist\n");
  467. return NULL;
  468. }
  469. /*
  470. * ACL_ATTR_IP and ACL_ATTR_DNS are initialized lazily in the
  471. * IpGetter and DnsGetter functions.
  472. * They are removed from the aclpb property list at acl__aclpb_done()
  473. * time.
  474. */
  475. /* allocate the acleval struct */
  476. aclpb->aclpb_acleval = (ACLEvalHandle_t *) ACL_EvalNew(NULL, NULL);
  477. if (aclpb->aclpb_acleval == NULL) {
  478. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  479. "Unable to allocate the acleval block\n");
  480. return NULL;
  481. }
  482. /*
  483. * This is a libaccess routine.
  484. * Need to setup subject and resource property information
  485. */
  486. ACL_EvalSetSubject(NULL, aclpb->aclpb_acleval, aclpb->aclpb_proplist);
  487. /* allocate some space for attr name */
  488. aclpb->aclpb_Evalattr = (char *) slapi_ch_malloc (ACLPB_MAX_ATTR_LEN);
  489. aclpb->aclpb_deny_handles = (aci_t **) slapi_ch_calloc (1,
  490. ACLPB_INCR_LIST_HANDLES * sizeof (aci_t *));
  491. aclpb->aclpb_allow_handles = (aci_t **) slapi_ch_calloc (1,
  492. ACLPB_INCR_LIST_HANDLES * sizeof (aci_t *));
  493. aclpb->aclpb_deny_handles_size = ACLPB_INCR_LIST_HANDLES;
  494. aclpb->aclpb_allow_handles_size = ACLPB_INCR_LIST_HANDLES;
  495. /* allocate the array for bases */
  496. aclpb->aclpb_grpsearchbase = (char **)
  497. slapi_ch_malloc (ACLPB_INCR_BASES * sizeof(char *));
  498. aclpb->aclpb_grpsearchbase_size = ACLPB_INCR_BASES;
  499. aclpb->aclpb_numof_bases = 0;
  500. /* Make sure aclpb_search_base is initialized to NULL..tested elsewhere! */
  501. aclpb->aclpb_search_base = NULL;
  502. aclpb->aclpb_authorization_sdn = slapi_sdn_new ();
  503. aclpb->aclpb_curr_entry_sdn = slapi_sdn_new();
  504. aclpb->aclpb_aclContainer = acllist_get_aciContainer_new ();
  505. /* hash table to store macro matched values from targets */
  506. aclpb->aclpb_macro_ht = acl_ht_new();
  507. return aclpb;
  508. }
  509. /* Initializes the aclpb */
  510. void
  511. acl_init_aclpb ( Slapi_PBlock *pb , Acl_PBlock *aclpb, const char *dn, int copy_from_aclcb)
  512. {
  513. struct acl_cblock *aclcb = NULL;
  514. char *authType;
  515. void *conn;
  516. unsigned long op_type;
  517. if ( NULL == aclpb ) {
  518. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name, "acl_init_aclpb:No ACLPB\n");
  519. return;
  520. }
  521. /* See if we have initialized already */
  522. if (aclpb->aclpb_state & ACLPB_INITIALIZED) return;
  523. slapi_pblock_get ( pb, SLAPI_OPERATION_TYPE, &op_type );
  524. if ( op_type == SLAPI_OPERATION_BIND || op_type == SLAPI_OPERATION_UNBIND )
  525. return;
  526. /* We indicate the initialize here becuase, if something goes wrong, it's cleaned up
  527. ** properly.
  528. */
  529. aclpb->aclpb_state = ACLPB_INITIALIZED;
  530. /* We make an anonymous user a non null dn which is empty */
  531. if (dn && *dn != '\0' )
  532. slapi_sdn_set_ndn_byval ( aclpb->aclpb_authorization_sdn, dn );
  533. else
  534. slapi_sdn_set_ndn_byval ( aclpb->aclpb_authorization_sdn, "" );
  535. /* reset scoped entry cache to be empty */
  536. aclpb->aclpb_scoped_entry_anominfo.anom_e_nummatched = 0;
  537. if (PListAssignValue(aclpb->aclpb_proplist, DS_ATTR_USERDN,
  538. slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn), 0) < 0) {
  539. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  540. "Unable to set the USER DN in the Plist\n");
  541. return;
  542. }
  543. slapi_pblock_get ( pb, SLAPI_OPERATION_AUTHTYPE, &authType );
  544. if (PListAssignValue(aclpb->aclpb_proplist, DS_ATTR_AUTHTYPE, authType, 0) < 0) {
  545. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  546. "Unable to set the AUTH TYPE in the Plist\n");
  547. return;
  548. }
  549. /* PKBxxx: We should be getting it from the OP struct */
  550. slapi_pblock_get ( pb, SLAPI_CONN_CERT, &aclpb->aclpb_clientcert );
  551. /* See if the we have already a cached info about user's group */
  552. aclg_init_userGroup ( aclpb, dn, 0 /* get lock */ );
  553. slapi_pblock_get( pb, SLAPI_BE_MAXNESTLEVEL, &aclpb->aclpb_max_nesting_level );
  554. slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &aclpb->aclpb_max_member_sizelimit );
  555. if ( aclpb->aclpb_max_member_sizelimit == 0 ) {
  556. aclpb->aclpb_max_member_sizelimit = SLAPD_DEFAULT_LOOKTHROUGHLIMIT;
  557. }
  558. slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &aclpb->aclpb_optype );
  559. aclpb->aclpb_signature = acl_get_aclsignature();
  560. aclpb->aclpb_last_cache_result = 0;
  561. aclpb->aclpb_pblock = pb;
  562. PR_ASSERT ( aclpb->aclpb_pblock != NULL );
  563. /* get the connection */
  564. slapi_pblock_get ( pb, SLAPI_CONNECTION, &conn);
  565. aclcb = (struct acl_cblock *) acl_get_ext ( ACL_EXT_CONNECTION, conn );
  566. if (NULL == aclcb || NULL == aclcb->aclcb_lock) {
  567. /* This could happen if the client is dead and we are in
  568. ** process of abondoning this operation
  569. */
  570. slapi_log_error( SLAPI_LOG_ACL, plugin_name,
  571. "No CONNECTION extension\n");
  572. } else if ( aclcb->aclcb_state == -1 ) {
  573. /* indicate that we need to update the cache */
  574. aclpb->aclpb_state |= ACLPB_UPD_ACLCB_CACHE;
  575. aclcb->aclcb_state = 0; /* Nore this is ACLCB and not ACLPB */
  576. } else if ( copy_from_aclcb ){
  577. char *cdn;
  578. Slapi_DN *c_sdn; /* client SDN */
  579. /* check if the operation is abandoned or not.*/
  580. if ( slapi_op_abandoned ( pb ) ) {
  581. return;
  582. }
  583. slapi_pblock_get ( pb, SLAPI_CONN_DN, &cdn ); /* We *must* free cdn! */
  584. c_sdn = slapi_sdn_new_dn_passin( cdn );
  585. PR_Lock ( aclcb->aclcb_lock );
  586. /*
  587. * since PR_Lock is taken,
  588. * we can mark the connection extension ok to be destroyed.
  589. */
  590. if ( (aclcb->aclcb_aclsignature != acl_get_aclsignature()) ||
  591. ( (NULL == cdn) && aclcb->aclcb_sdn ) ||
  592. (cdn && (NULL == aclcb->aclcb_sdn )) ||
  593. (cdn && aclcb->aclcb_sdn && ( 0 != slapi_sdn_compare ( c_sdn, aclcb->aclcb_sdn ) ))) {
  594. /* cleanup the aclcb cache */
  595. acl_clean_aclEval_context ( &aclcb->aclcb_eval_context, 0 /*clean*/ );
  596. aclcb->aclcb_state = 0;
  597. aclcb->aclcb_aclsignature = 0;
  598. slapi_sdn_done ( aclcb->aclcb_sdn );
  599. }
  600. slapi_sdn_free ( &c_sdn );
  601. /* COPY the cached information from ACLCB --> ACLPB */
  602. if ( aclcb->aclcb_state & ACLCB_HAS_CACHED_EVALCONTEXT) {
  603. acl_copyEval_context ( aclpb, &aclcb->aclcb_eval_context ,
  604. &aclpb->aclpb_prev_opEval_context, 0 );
  605. aclpb->aclpb_state |= ACLPB_HAS_ACLCB_EVALCONTEXT;
  606. }
  607. PR_Unlock ( aclcb->aclcb_lock );
  608. }
  609. }
  610. /* Cleans up the aclpb */
  611. static void
  612. acl__done_aclpb ( struct acl_pblock *aclpb )
  613. {
  614. int i;
  615. int dump_aclpb_info = 0;
  616. int rc=-1;
  617. char *tmp_ptr=NULL;
  618. /*
  619. ** First, let's do some sanity checks to see if we have everything what
  620. ** it should be.
  621. */
  622. /* Nothing needs to be cleaned up in this case */
  623. if ( !aclpb->aclpb_state & ACLPB_INITIALIZED)
  624. return;
  625. /* Check the state */
  626. if (aclpb->aclpb_state & ~ACLPB_STATE_ALL) {
  627. slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
  628. "The aclpb.state value (%d) is incorrect. Exceeded the limit (%d)\n",
  629. aclpb->aclpb_state, ACLPB_STATE_ALL);
  630. dump_aclpb_info = 1;
  631. }
  632. /* acl__dump_stats ( aclpb, acl__get_aclpb_type(aclpb)); */
  633. /* reset the usergroup cache */
  634. aclg_reset_userGroup ( aclpb );
  635. if ( aclpb->aclpb_res_type & ~ACLPB_RESTYPE_ALL ) {
  636. slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
  637. "The aclpb res_type value (%d) has exceeded. Limit is (%d)\n",
  638. aclpb->aclpb_res_type, ACLPB_RESTYPE_ALL, 0 );
  639. dump_aclpb_info = 1;
  640. }
  641. if ( dump_aclpb_info ) {
  642. const char *ndn;
  643. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  644. "ACLPB value is:%p\n", aclpb, 0,0 );
  645. ndn = slapi_sdn_get_ndn ( aclpb->aclpb_curr_entry_sdn );
  646. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name, "curr_entry:%p num_entries:%d curr_dn:%p\n",
  647. aclpb->aclpb_curr_entry ? (char *) aclpb->aclpb_curr_entry : "NULL",
  648. aclpb->aclpb_num_entries,
  649. ndn ? ndn : "NULL");
  650. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name, "Last attr:%p, Plist:%p acleval: %p\n",
  651. aclpb->aclpb_Evalattr ? aclpb->aclpb_Evalattr : "NULL",
  652. aclpb->aclpb_proplist ? (char *) aclpb->aclpb_proplist : "NULL",
  653. aclpb->aclpb_acleval ? (char *) aclpb->aclpb_acleval : "NULL" );
  654. }
  655. /* Now Free the contents or clean it */
  656. slapi_sdn_done ( aclpb->aclpb_curr_entry_sdn );
  657. if (aclpb->aclpb_Evalattr)
  658. aclpb->aclpb_Evalattr[0] = '\0';
  659. /* deallocate the contents of the base array */
  660. for (i=0; i < aclpb->aclpb_numof_bases; i++) {
  661. if (aclpb->aclpb_grpsearchbase[i])
  662. slapi_ch_free ( (void **)&aclpb->aclpb_grpsearchbase[i] );
  663. }
  664. aclpb->aclpb_numof_bases = 0;
  665. acl_clean_aclEval_context ( &aclpb->aclpb_prev_opEval_context, 0 /*claen*/ );
  666. acl_clean_aclEval_context ( &aclpb->aclpb_prev_entryEval_context, 0 /*clean*/ );
  667. acl_clean_aclEval_context ( &aclpb->aclpb_curr_entryEval_context, 0/*clean*/ );
  668. if ( aclpb->aclpb_client_entry ) slapi_entry_free ( aclpb->aclpb_client_entry );
  669. aclpb->aclpb_client_entry = NULL;
  670. slapi_sdn_done ( aclpb->aclpb_authorization_sdn );
  671. aclpb->aclpb_pblock = NULL;
  672. if ( aclpb->aclpb_search_base )
  673. slapi_ch_free ( (void **) &aclpb->aclpb_search_base );
  674. for ( i=0; i < aclpb->aclpb_num_deny_handles; i++ )
  675. aclpb->aclpb_deny_handles[i] = NULL;
  676. aclpb->aclpb_num_deny_handles = 0;
  677. for ( i=0; i < aclpb->aclpb_num_allow_handles; i++ )
  678. aclpb->aclpb_allow_handles[i] = NULL;
  679. aclpb->aclpb_num_allow_handles = 0;
  680. /* clear results cache */
  681. memset((char*)aclpb->aclpb_cache_result, 0,
  682. sizeof(struct result_cache)*aclpb->aclpb_last_cache_result);
  683. aclpb->aclpb_last_cache_result = 0;
  684. aclpb->aclpb_handles_index[0] = -1;
  685. aclpb->aclpb_base_handles_index[0] = -1;
  686. aclpb->aclpb_stat_acllist_scanned = 0;
  687. aclpb->aclpb_stat_aclres_matched = 0;
  688. aclpb->aclpb_stat_total_entries = 0;
  689. aclpb->aclpb_stat_anom_list_scanned = 0;
  690. aclpb->aclpb_stat_num_copycontext = 0;
  691. aclpb->aclpb_stat_num_copy_attrs = 0;
  692. aclpb->aclpb_stat_num_tmatched_acls = 0;
  693. aclpb->aclpb_clientcert = NULL;
  694. aclpb->aclpb_proxy = NULL;
  695. acllist_done_aciContainer ( aclpb->aclpb_aclContainer );
  696. /*
  697. * Here, decide which things need to be freed/removed/whatever from the
  698. * aclpb_proplist.
  699. */
  700. /*
  701. * The DS_ATTR_DNS property contains the name of the client machine.
  702. *
  703. * The value pointed to by this property is stored in the pblock--it
  704. * points to the SLAPI_CLIENT_DNS object. So, that memory will
  705. * be freed elsewhere.
  706. *
  707. * It's removed here from the aclpb_proplist as it would be an error to
  708. * allow it to persist in the aclpb which is an operation time thing.
  709. * If we leave it here the next time this aclpb gets used, the DnsGetter
  710. * is not called by LASDnsEval/ACL_GetAttribute() as it thinks the
  711. * ACL_ATTR_DNS has already been initialized.
  712. *
  713. */
  714. if ((rc = PListFindValue(aclpb->aclpb_proplist, ACL_ATTR_DNS,
  715. (void **)&tmp_ptr, NULL)) > 0) {
  716. PListDeleteProp(aclpb->aclpb_proplist, rc, NULL);
  717. }
  718. /*
  719. * Remove the DS_ATTR_IP property from the property list.
  720. * The value of this property is just the property pointer
  721. * (an unsigned long) so that gets freed too when we delete the
  722. * property.
  723. * It's removed here from the aclpb_proplist as it would be an error to
  724. * allow it to persist in the aclpb which is an operation time thing.
  725. * If we leave it here the next time this aclpb gets used, the DnsGetter
  726. * is not called by LASIpEval/ACL_GetAttribute() as it thinks the
  727. * ACL_ATTR_IP has already been initialized.
  728. */
  729. if ((rc = PListFindValue(aclpb->aclpb_proplist, ACL_ATTR_IP,
  730. (void **)&tmp_ptr, NULL)) > 0) {
  731. PListDeleteProp(aclpb->aclpb_proplist, rc, NULL);
  732. }
  733. /*
  734. * The DS_ATTR_USERDN value comes from aclpb_authorization_sdn.
  735. * This memory
  736. * is freed above using aclpb_authorization_sdn so we don't need to free it here
  737. * before overwriting the old value.
  738. */
  739. PListAssignValue(aclpb->aclpb_proplist, DS_ATTR_USERDN, NULL, 0);
  740. /*
  741. * The DS_ATTR_AUTHTYPE value is a pointer into the pblock, so
  742. * we do not need to free that memory before overwriting the value.
  743. */
  744. PListAssignValue(aclpb->aclpb_proplist, DS_ATTR_AUTHTYPE, NULL, 0);
  745. /*
  746. * DO NOT overwrite the aclpb pointer--it is initialized at malloc_aclpb
  747. * time and is kept within the aclpb.
  748. *
  749. * PListAssignValue(aclpb->aclpb_proplist, DS_PROP_ACLPB, NULL, 0);
  750. */
  751. /*
  752. * The DS_ATTR_ENTRY value was a pointer to the entry being evaluated
  753. * by the ACL code. That entry comes from outside the context of
  754. * the acl code and so is dealt with out there. Ergo, here we can just
  755. * lose the pointer to that entry.
  756. */
  757. PListAssignValue(aclpb->aclpb_proplist, DS_ATTR_ENTRY, NULL, 0);
  758. aclpb->aclpb_signature = 0;
  759. /* reset scoped entry cache to be empty */
  760. aclpb->aclpb_scoped_entry_anominfo.anom_e_nummatched = 0;
  761. /* Free up any of the string values left in the macro ht and remove
  762. * the entries.*/
  763. acl_ht_free_all_entries_and_values(aclpb->aclpb_macro_ht);
  764. /* Finally, set it to the no use state */
  765. aclpb->aclpb_state = 0;
  766. }
  767. static char *
  768. acl__get_aclpb_type ( Acl_PBlock *aclpb )
  769. {
  770. if (aclpb->aclpb_state & ACLPB_TYPE_PROXY)
  771. return ACLPB_TYPE_PROXY_STR;
  772. return ACLPB_TYPE_MAIN_STR;
  773. }
  774. static void
  775. acl__dump_stats ( struct acl_pblock *aclpb , const char *block_type)
  776. {
  777. int connid = 0;
  778. int opid = 0;
  779. Slapi_PBlock *pb = NULL;
  780. pb = aclpb->aclpb_pblock;
  781. if ( pb ) {
  782. slapi_pblock_get ( pb, SLAPI_CONN_ID, &connid );
  783. slapi_pblock_get ( pb, SLAPI_OPERATION_ID, &opid );
  784. }
  785. /* DUMP STAT INFO */
  786. slapi_log_error( SLAPI_LOG_ACL, plugin_name,
  787. "**** ACL OPERATION STAT BEGIN ( aclpb:%p Block type: %s): Conn:%d Operation:%d *******\n",
  788. aclpb, block_type, connid, opid );
  789. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of entries scanned: %d\n",
  790. aclpb->aclpb_stat_total_entries);
  791. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of times ACL List scanned: %d\n",
  792. aclpb->aclpb_stat_acllist_scanned);
  793. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of ACLs with target matched:%d\n",
  794. aclpb->aclpb_stat_num_tmatched_acls);
  795. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of times acl resource matched:%d\n",
  796. aclpb->aclpb_stat_aclres_matched);
  797. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of times ANOM list scanned:%d\n",
  798. aclpb->aclpb_stat_anom_list_scanned);
  799. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of times Context was copied:%d\n",
  800. aclpb->aclpb_stat_num_copycontext);
  801. slapi_log_error( SLAPI_LOG_ACL, plugin_name, "\tNumber of times Attrs was copied:%d\n",
  802. aclpb->aclpb_stat_num_copy_attrs);
  803. slapi_log_error( SLAPI_LOG_ACL, plugin_name, " **** ACL OPERATION STAT END *******\n");
  804. }
  805. /****************************************************************************/
  806. /* E N D */
  807. /****************************************************************************/