aclinit.c 18 KB

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