aclinit.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright 2001 Sun Microsystems, Inc.
  3. * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. #include "acl.h"
  7. static int __aclinit__RegisterLases(void);
  8. static int __aclinit__RegisterAttributes(void);
  9. static int __aclinit_handler(Slapi_Entry *e, void *callback_data);
  10. /***************************************************************************
  11. *
  12. * aclinit_main()
  13. * Main routine which is called at the server boot up time.
  14. *
  15. * 1) Reads all the ACI entries from the database and creates
  16. * the ACL list.
  17. * 2) Registers all the LASes and the GetAttrs supported by the DS.
  18. * 3) Generates anonymous profiles.
  19. * 4) Registers proxy control
  20. * 5) Creates aclpb pool
  21. *
  22. * Input:
  23. * None.
  24. *
  25. * Returns:
  26. * 0 -- no error
  27. * 1 -- Error
  28. *
  29. * Error Handling:
  30. * If any error found during the ACL generation, error is logged.
  31. *
  32. **************************************************************************/
  33. static int acl_initialized = 0;
  34. int
  35. aclinit_main()
  36. {
  37. char *cookie = NULL;
  38. Slapi_PBlock *pb;
  39. int rv;
  40. Slapi_DN *sdn;
  41. void *node;
  42. if (acl_initialized) {
  43. /* There is no need to do anything more */
  44. return 0;
  45. }
  46. /* Initialize the LIBACCESS ACL library */
  47. if (ACL_Init() != 0) {
  48. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  49. "ACL Library Initialization failed\n",0,0,0);
  50. return 1;
  51. }
  52. /* register all the LASes supported by the DS */
  53. if (ACL_ERR == __aclinit__RegisterLases()) {
  54. /* Error is already logged */
  55. return 1;
  56. }
  57. /* Register all the Attrs */
  58. if (ACL_ERR == __aclinit__RegisterAttributes()) {
  59. /* Error is already logged */
  60. return 1;
  61. }
  62. /*
  63. * Register to get backend state changes so we can add/remove
  64. * acis from backends that come up and go down.
  65. */
  66. slapi_register_backend_state_change((void *) NULL, acl_be_state_change_fnc);
  67. /* register the extensions */
  68. /* ONREPL Moved to the acl_init function because extensions
  69. need to be registered before any operations are issued
  70. if ( 0 != acl_init_ext() ) {
  71. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  72. "Unable to initialize the extensions\n");
  73. return 1;
  74. } */
  75. /* create the mutex array */
  76. if ( 0 != aclext_alloc_lockarray ( ) ) {
  77. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  78. "Unable to create the mutext array\n");
  79. return 1;
  80. }
  81. /* Allocate the pool */
  82. if ( 0 != acl_create_aclpb_pool () ) {
  83. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  84. "Unable to create the acl private pool\n");
  85. return 1;
  86. }
  87. /*
  88. * Now read all the ACLs from all the backends and put it
  89. * in a list
  90. */
  91. /* initialize the ACLLIST sub-system */
  92. if ( 0 != (rv = acllist_init ( ))) {
  93. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  94. "Unable to initialize the plugin:%d\n", rv );
  95. return 1;
  96. }
  97. /* Initialize the anonymous profile i.e., generate it */
  98. rv = aclanom_init ();
  99. pb = slapi_pblock_new();
  100. /*
  101. * search for the aci_attr_type attributes of all entries.
  102. *
  103. * slapi_get_fist_suffix() and slapi_get_next_suffix() do not return the
  104. * rootdse entry so we search for acis in there explicitly here.
  105. */
  106. sdn = slapi_sdn_new_dn_byval("");
  107. slapi_log_error ( SLAPI_LOG_ACL, plugin_name,
  108. "Searching for all acis(scope base) at suffix ''\n");
  109. aclinit_search_and_update_aci ( 0, /* thisbeonly */
  110. sdn, /* base */
  111. NULL, /* be name*/
  112. LDAP_SCOPE_BASE, ACL_ADD_ACIS,
  113. DO_TAKE_ACLCACHE_WRITELOCK);
  114. slapi_sdn_free(&sdn);
  115. sdn = slapi_get_first_suffix( &node, 1 );
  116. while (sdn)
  117. {
  118. slapi_log_error ( SLAPI_LOG_ACL, plugin_name,
  119. "Searching for all acis(scope subtree) at suffix '%s'\n",
  120. slapi_sdn_get_dn(sdn) );
  121. aclinit_search_and_update_aci ( 0, /* thisbeonly */
  122. sdn, /* base */
  123. NULL, /* be name*/
  124. LDAP_SCOPE_SUBTREE, ACL_ADD_ACIS,
  125. DO_TAKE_ACLCACHE_WRITELOCK);
  126. sdn = slapi_get_next_suffix( &node, 1 );
  127. }
  128. /* Initialize it. */
  129. acl_initialized = 1;
  130. /* generate the signatures */
  131. acl_set_aclsignature ( aclutil_gen_signature ( 100 ) );
  132. /* Initialize the user-group cache */
  133. rv = aclgroup_init ( );
  134. aclanom_gen_anomProfile (DO_TAKE_ACLCACHE_READLOCK);
  135. /* Register both of the proxied authorization controls (version 1 and 2) */
  136. slapi_register_supported_control( LDAP_CONTROL_PROXYAUTH,
  137. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  138. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  139. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN
  140. | SLAPI_OPERATION_EXTENDED );
  141. slapi_register_supported_control( LDAP_CONTROL_PROXIEDAUTH,
  142. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  143. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  144. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN
  145. | SLAPI_OPERATION_EXTENDED );
  146. slapi_pblock_destroy ( pb );
  147. return 0;
  148. }
  149. /*
  150. * This routine is the one that scans for acis and either adds them
  151. * to the internal cache (op==ACL_ADD_ACIS) or deletes them
  152. * (op==ACL_REMOVE_ACIS).
  153. *
  154. * If thisbeonly is 0 the search
  155. * is conducted on the base with the specifed scope and be_name is ignored.
  156. * This is used at startup time where we iterate over all suffixes, searching
  157. * for all the acis in the DIT to load the ACL cache.
  158. *
  159. * If thisbeonly is 1 then then a be_name must be specified.
  160. * In this case we will search in that backend ONLY.
  161. * This is used in the case where a backend is turned on and off--in this
  162. * case we only want to add/remove the acis in that particular backend and
  163. * not for example in any backends below that one.
  164. */
  165. int
  166. aclinit_search_and_update_aci ( int thisbeonly, const Slapi_DN *base,
  167. char *be_name, int scope, int op,
  168. acl_lock_flag_t lock_flag )
  169. {
  170. char *attrs[2] = { "aci", NULL };
  171. /* Tell __aclinit_handler whether it's an add or a delete */
  172. int any_error = op;
  173. Slapi_PBlock *aPb;
  174. LDAPControl **ctrls=NULL;
  175. int retval;
  176. struct berval *bval;
  177. aclinit_handler_callback_data_t call_back_data;
  178. PR_ASSERT( lock_flag == DONT_TAKE_ACLCACHE_WRITELOCK ||
  179. lock_flag == DO_TAKE_ACLCACHE_WRITELOCK);
  180. if ( thisbeonly && be_name == NULL) {
  181. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  182. "Error: This be_name must be specified.\n", 0, 0, 0);
  183. return -1;
  184. }
  185. /*
  186. * We need to explicitly request (objectclass=ldapsubentry)
  187. * in order to get all the subentry acis too.
  188. * Note that subentries can be added under subentries (although its not
  189. * recommended) so that
  190. * there may be non-trivial acis under a subentry.
  191. */
  192. /* Use new search internal API */
  193. /* and never retrieve aci from a remote server */
  194. aPb = slapi_pblock_new ();
  195. /*
  196. * Set up the control to say "Only get acis from this Backend--
  197. * there may be more backends under this one.
  198. */
  199. if ( thisbeonly ) {
  200. bval = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  201. bval->bv_len = strlen(be_name) + 1;
  202. bval->bv_val = slapi_ch_strdup(be_name);
  203. ctrls = (LDAPControl **)slapi_ch_calloc( 2, sizeof(LDAPControl *));
  204. ctrls[0] = NULL;
  205. ctrls[1] = NULL;
  206. retval = slapi_build_control_from_berval(
  207. MTN_CONTROL_USE_ONE_BACKEND_OID,
  208. bval,
  209. 1 /* is critical */,
  210. ctrls);
  211. }
  212. slapi_search_internal_set_pb ( aPb,
  213. slapi_sdn_get_dn(base),
  214. scope,
  215. "(|(aci=*)(objectclass=ldapsubentry))",
  216. attrs,
  217. 0 /* attrsonly */,
  218. ctrls /* controls: SLAPI_ARGCONTROLS */,
  219. NULL /* uniqueid */,
  220. aclplugin_get_identity (ACL_PLUGIN_IDENTITY),
  221. SLAPI_OP_FLAG_NEVER_CHAIN /* actions : get local aci only */);
  222. if (thisbeonly) {
  223. slapi_pblock_set(aPb, SLAPI_REQCONTROLS, ctrls);
  224. }
  225. call_back_data.op = op;
  226. call_back_data.retCode = 0;
  227. call_back_data.lock_flag = lock_flag;
  228. slapi_search_internal_callback_pb(aPb,
  229. &call_back_data /* callback_data */,
  230. NULL/* result_callback */,
  231. __aclinit_handler,
  232. NULL /* referral_callback */);
  233. if (thisbeonly) {
  234. slapi_ch_free((void **)&bval);
  235. }
  236. /*
  237. * This frees the control oid, the bv_val and the control itself and the
  238. * ctrls array mem by caling ldap_controls_free()--so we
  239. * don't need to do it ourselves.
  240. */
  241. slapi_pblock_destroy (aPb);
  242. return call_back_data.retCode;
  243. }
  244. /***************************************************************************
  245. *
  246. * __aclinit_handler
  247. *
  248. * For each entry, finds if there is any ACL in thet entry. If there is
  249. * then the ACL is processed and stored in the ACL LIST.
  250. *
  251. *
  252. * Input:
  253. *
  254. *
  255. * Returns:
  256. * None.
  257. *
  258. * Error Handling:
  259. * If any error found during the ACL generation, the ACL is
  260. * logged. Also, set in the callback_data so that caller can act upon it.
  261. *
  262. **************************************************************************/
  263. static int
  264. __aclinit_handler ( Slapi_Entry *e, void *callback_data)
  265. {
  266. Slapi_Attr *attr;
  267. aclinit_handler_callback_data_t *call_back_data =
  268. (aclinit_handler_callback_data_t*)callback_data;
  269. Slapi_DN *e_sdn;
  270. int rv;
  271. Slapi_Value *sval=NULL;
  272. call_back_data->retCode = 0; /* assume success--if there's an error we overwrite it */
  273. if (e != NULL) {
  274. e_sdn = slapi_entry_get_sdn ( e );
  275. /*
  276. * Take the write lock around all the mods--so that
  277. * other operations will see the acicache either before the whole mod
  278. * or after but not, as it was before, during the mod.
  279. * This is in line with the LDAP concept of the operation
  280. * on the whole entry being the atomic unit.
  281. *
  282. */
  283. if ( call_back_data->op == ACL_ADD_ACIS ) {
  284. slapi_log_error ( SLAPI_LOG_ACL, plugin_name,
  285. "Adding acis for entry '%s'\n", slapi_sdn_get_dn(e_sdn));
  286. slapi_entry_attr_find ( e, aci_attr_type, &attr );
  287. if ( attr ) {
  288. const struct berval *attrValue;
  289. int i;
  290. if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) {
  291. acllist_acicache_WRITE_LOCK();
  292. }
  293. i= slapi_attr_first_value ( attr, &sval );
  294. while(i != -1) {
  295. attrValue = slapi_value_get_berval(sval);
  296. if ( 0 != (rv=acllist_insert_aci_needsLock (e_sdn, attrValue))) {
  297. aclutil_print_err(rv, e_sdn, attrValue, NULL);
  298. /* We got an error; Log it and then march along */
  299. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  300. "Error: This (%s) ACL will not be considered for evaluation"
  301. " because of syntax errors.\n",
  302. attrValue->bv_val ? attrValue->bv_val: "NULL", 0, 0);
  303. call_back_data->retCode = rv;
  304. }
  305. i= slapi_attr_next_value( attr, i, &sval );
  306. }/* while */
  307. if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) {
  308. acllist_acicache_WRITE_UNLOCK();
  309. }
  310. }
  311. } else if (call_back_data->op == ACL_REMOVE_ACIS) {
  312. /* Here we are deleting the acis. */
  313. slapi_log_error ( SLAPI_LOG_ACL, plugin_name, "Removing acis\n");
  314. if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) {
  315. acllist_acicache_WRITE_LOCK();
  316. }
  317. if ( 0 != (rv=acllist_remove_aci_needsLock(e_sdn, NULL))) {
  318. aclutil_print_err(rv, e_sdn, NULL, NULL);
  319. /* We got an error; Log it and then march along */
  320. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  321. "Error: ACls not deleted from %s\n",
  322. e_sdn, 0, 0);
  323. call_back_data->retCode = rv;
  324. }
  325. if ( call_back_data->lock_flag == DO_TAKE_ACLCACHE_WRITELOCK) {
  326. acllist_acicache_WRITE_UNLOCK();
  327. }
  328. }
  329. }
  330. /*
  331. * If we get here it's success.
  332. * The call_back_data->error is the error code that counts as it's the
  333. * one that the original caller will see--this routine is called off a callbacl.
  334. */
  335. return ACL_FALSE; /* "local" error code--it's 0 */
  336. }
  337. /***************************************************************************
  338. *
  339. * __acl__RegisterAttributes
  340. *
  341. * Register all the attributes supported by the DS.
  342. *
  343. * Input:
  344. * None.
  345. *
  346. * Returns:
  347. * ACL_OK - No error
  348. * ACL_ERR - in case of errror
  349. *
  350. * Error Handling:
  351. * None.
  352. *
  353. **************************************************************************/
  354. static int
  355. __aclinit__RegisterAttributes(void)
  356. {
  357. ACLMethod_t methodinfo;
  358. NSErr_t errp;
  359. int rv;
  360. memset (&errp, 0, sizeof(NSErr_t));
  361. rv = ACL_MethodRegister(&errp, DS_METHOD, &methodinfo);
  362. if (rv < 0) {
  363. acl_print_acllib_err(&errp, NULL);
  364. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  365. "Unable to Register the methods\n", 0,0,0);
  366. return ACL_ERR;
  367. }
  368. rv = ACL_MethodSetDefault (&errp, methodinfo);
  369. if (rv < 0) {
  370. acl_print_acllib_err(&errp, NULL);
  371. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  372. "Unable to Set the default method\n", 0,0,0);
  373. return ACL_ERR;
  374. }
  375. rv = ACL_AttrGetterRegister(&errp, ACL_ATTR_IP, DS_LASIpGetter,
  376. methodinfo, ACL_DBTYPE_ANY, ACL_AT_FRONT, NULL);
  377. if (rv < 0) {
  378. acl_print_acllib_err(&errp, NULL);
  379. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  380. "Unable to Register Attr ip\n", 0,0,0);
  381. return ACL_ERR;
  382. }
  383. rv = ACL_AttrGetterRegister(&errp, ACL_ATTR_DNS, DS_LASDnsGetter,
  384. methodinfo, ACL_DBTYPE_ANY, ACL_AT_FRONT, NULL);
  385. if (rv < 0) {
  386. acl_print_acllib_err(&errp, NULL);
  387. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  388. "Unable to Register Attr dns\n", 0,0,0);
  389. return ACL_ERR;
  390. }
  391. return ACL_OK;
  392. }
  393. /***************************************************************************
  394. *
  395. * __acl__RegisterLases
  396. * Register all the LASes supported by the DS.
  397. *
  398. * The DS doesnot support user/group. We have defined our own LAS
  399. * so that we can display/print an error when the LAS is invoked.
  400. * Input:
  401. * None.
  402. *
  403. * Returns:
  404. * ACL_OK - No error
  405. * ACL_ERR - in case of errror
  406. *
  407. * Error Handling:
  408. * None.
  409. *
  410. **************************************************************************/
  411. static int
  412. __aclinit__RegisterLases(void)
  413. {
  414. if (ACL_LasRegister(NULL, DS_LAS_USER, (LASEvalFunc_t) DS_LASUserEval,
  415. (LASFlushFunc_t) NULL) < 0) {
  416. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  417. "Unable to register USER Las\n",0,0,0);
  418. return ACL_ERR;
  419. }
  420. if (ACL_LasRegister(NULL, DS_LAS_GROUP, (LASEvalFunc_t) DS_LASGroupEval,
  421. (LASFlushFunc_t) NULL) < 0) {
  422. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  423. "Unable to register GROUP Las\n",0,0,0);
  424. return ACL_ERR;
  425. }
  426. if (ACL_LasRegister(NULL, DS_LAS_GROUPDN, (LASEvalFunc_t)DS_LASGroupDnEval,
  427. (LASFlushFunc_t)NULL) < 0) {
  428. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  429. "Unable to register GROUPDN Las\n",0,0,0);
  430. return ACL_ERR;
  431. }
  432. if (ACL_LasRegister(NULL, DS_LAS_ROLEDN, (LASEvalFunc_t)DS_LASRoleDnEval,
  433. (LASFlushFunc_t)NULL) < 0) {
  434. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  435. "Unable to register ROLEDN Las\n",0,0,0);
  436. return ACL_ERR;
  437. }
  438. if (ACL_LasRegister(NULL, DS_LAS_USERDN, (LASEvalFunc_t)DS_LASUserDnEval,
  439. (LASFlushFunc_t)NULL) < 0) {
  440. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  441. "Unable to register USERDN Las\n",0,0,0);
  442. return ACL_ERR;
  443. }
  444. if (ACL_LasRegister(NULL, DS_LAS_USERDNATTR,
  445. (LASEvalFunc_t)DS_LASUserDnAttrEval,
  446. (LASFlushFunc_t)NULL) < 0) {
  447. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  448. "Unable to register USERDNATTR Las\n",0,0,0);
  449. return ACL_ERR;
  450. }
  451. if (ACL_LasRegister(NULL, DS_LAS_AUTHMETHOD,
  452. (LASEvalFunc_t)DS_LASAuthMethodEval,
  453. (LASFlushFunc_t)NULL) < 0) {
  454. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  455. "Unable to register CLIENTAUTHTYPE Las\n",0,0,0);
  456. return ACL_ERR;
  457. }
  458. if (ACL_LasRegister(NULL, DS_LAS_GROUPDNATTR,
  459. (LASEvalFunc_t)DS_LASGroupDnAttrEval,
  460. (LASFlushFunc_t)NULL) < 0) {
  461. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  462. "Unable to register GROUPDNATTR Las\n",0,0,0);
  463. return ACL_ERR;
  464. }
  465. if (ACL_LasRegister(NULL, DS_LAS_USERATTR,
  466. (LASEvalFunc_t)DS_LASUserAttrEval,
  467. (LASFlushFunc_t)NULL) < 0) {
  468. slapi_log_error (SLAPI_LOG_FATAL, plugin_name,
  469. "Unable to register USERATTR Las\n",0,0,0);
  470. return ACL_ERR;
  471. }
  472. return ACL_OK;
  473. }