1
0

oneeval.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /*
  13. * Description (acleval.c)
  14. *
  15. * This module provides functions for evaluating Access Control List
  16. * (ACL) structures in memory.
  17. *
  18. */
  19. #include <string.h>
  20. #include <sys/types.h>
  21. #include <assert.h>
  22. #include <netsite.h>
  23. #include <base/systems.h>
  24. #include <base/crit.h>
  25. #include <libaccess/nserror.h>
  26. #include <libaccess/acl.h>
  27. #include "aclpriv.h"
  28. #include <libaccess/aclproto.h>
  29. #include <libaccess/las.h>
  30. #include <libaccess/symbols.h>
  31. #include <libaccess/aclerror.h>
  32. #include <libaccess/aclglobal.h>
  33. #include <libaccess/dbtlibaccess.h>
  34. #include <libaccess/aclerror.h>
  35. #include "access_plhash.h"
  36. #include "aclutil.h"
  37. #include "aclcache.h"
  38. #include "oneeval.h"
  39. #define NO_ACL_HASH_FUNCS
  40. #include "permhash.h"
  41. static ACLDispatchVector_t __nsacl_vector = {
  42. /* Error frame stack support */
  43. nserrDispose,
  44. nserrFAlloc,
  45. nserrFFree,
  46. nserrGenerate,
  47. /* Property list support */
  48. PListAssignValue,
  49. PListCreate,
  50. PListDefProp,
  51. PListDeleteProp,
  52. PListFindValue,
  53. PListInitProp,
  54. PListNew,
  55. PListDestroy,
  56. PListGetValue,
  57. PListNameProp,
  58. PListSetType,
  59. PListSetValue,
  60. PListEnumerate,
  61. PListDuplicate,
  62. PListGetPool,
  63. /* ACL attribute handling */
  64. ACL_LasRegister,
  65. /* method/dbtype registration routines */
  66. ACL_MethodRegister,
  67. ACL_MethodIsEqual,
  68. ACL_MethodNameIsEqual,
  69. ACL_MethodFind,
  70. ACL_MethodGetDefault,
  71. ACL_MethodSetDefault,
  72. ACL_AuthInfoGetMethod,
  73. ACL_DbTypeRegister,
  74. ACL_DbTypeIsEqual,
  75. ACL_DbTypeNameIsEqual,
  76. ACL_DbTypeFind,
  77. ACL_DbTypeGetDefault,
  78. ACL_AuthInfoGetDbType,
  79. ACL_DbTypeIsRegistered,
  80. ACL_DbTypeParseFn,
  81. ACL_AttrGetterRegister,
  82. ACL_ModuleRegister,
  83. ACL_GetAttribute,
  84. ACL_DatabaseRegister,
  85. ACL_DatabaseFind,
  86. ACL_DatabaseSetDefault,
  87. NULL,
  88. ACL_AuthInfoGetDbname,
  89. ACL_CacheFlushRegister,
  90. ACL_CacheFlush,
  91. /* ACL language and file interfaces */
  92. NULL /* ex ACL_ParseFile*/,
  93. ACL_ParseString,
  94. NULL /* ex ACL_WriteString*/,
  95. NULL /* ex ACL_WriteFile */,
  96. NULL /* ex ACL_FileRenameAcl */,
  97. NULL /* ex ACL_FileDeleteAcl */,
  98. NULL /* ex ACL_FileGetAcl */,
  99. NULL /* ex ACL_FileSetAcl */,
  100. /* ACL Expression construction interfaces */
  101. ACL_ExprNew,
  102. ACL_ExprDestroy,
  103. ACL_ExprSetPFlags,
  104. ACL_ExprClearPFlags,
  105. ACL_ExprTerm,
  106. ACL_ExprNot,
  107. ACL_ExprAnd,
  108. ACL_ExprOr,
  109. ACL_ExprAddAuthInfo,
  110. ACL_ExprAddArg,
  111. ACL_ExprSetDenyWith,
  112. ACL_ExprGetDenyWith,
  113. ACL_ExprAppend,
  114. /* ACL manipulation */
  115. ACL_AclNew,
  116. ACL_AclDestroy,
  117. /* ACL list manipulation */
  118. ACL_ListNew,
  119. ACL_ListConcat,
  120. ACL_ListAppend,
  121. ACL_ListDestroy,
  122. ACL_ListFind,
  123. ACL_ListAclDelete,
  124. ACL_ListGetNameList,
  125. ACL_NameListDestroy,
  126. /* ACL evaluation */
  127. ACL_EvalTestRights,
  128. ACL_EvalNew,
  129. ACL_EvalDestroy,
  130. ACL_EvalSetACL,
  131. ACL_EvalGetSubject,
  132. ACL_EvalSetSubject,
  133. ACL_EvalGetResource,
  134. ACL_EvalSetResource,
  135. /* Access to critical section for ACL cache */
  136. ACL_CritEnter,
  137. ACL_CritExit,
  138. /* Miscellaneous functions */
  139. ACL_AclGetTag,
  140. ACL_ListGetFirst,
  141. ACL_ListGetNext,
  142. /* Functions added after ES 3.0 release */
  143. ACL_DatabaseGetDefault,
  144. ACL_SetDefaultResult,
  145. ACL_GetDefaultResult
  146. };
  147. NSAPI_PUBLIC ACLDispatchVector_t *__nsacl_table = &__nsacl_vector;
  148. int ACLEvalAce(
  149. NSErr_t *errp,
  150. ACLEvalHandle_t *acleval,
  151. ACLExprHandle_t *ace,
  152. ACLCachable_t *cachable,
  153. PList_t autharray[],
  154. PList_t global_auth
  155. )
  156. {
  157. ACLCachable_t local_cachable;
  158. int result;
  159. ACLExprEntry_t *expr;
  160. int expr_index = 0;
  161. expr = &ace->expr_arry[0];
  162. *cachable = ACL_INDEF_CACHABLE;
  163. while (TRUE)
  164. {
  165. local_cachable = ACL_NOT_CACHABLE;
  166. /* Call the LAS driver */
  167. if (!expr->las_eval_func) {
  168. ACL_CritEnter();
  169. if (!expr->las_eval_func) { /* Must check again after locking */
  170. ACL_LasFindEval(errp, expr->attr_name, &expr->las_eval_func);
  171. if (!expr->las_eval_func) { /* Couldn't find it */
  172. ACL_CritExit();
  173. return LAS_EVAL_INVALID;
  174. }
  175. }
  176. ACL_CritExit();
  177. }
  178. result = (*expr->las_eval_func)(
  179. errp,
  180. expr->attr_name,
  181. expr->comparator,
  182. expr->attr_pattern,
  183. &local_cachable,
  184. &expr->las_cookie,
  185. acleval->subject,
  186. acleval->resource,
  187. autharray ? autharray[expr_index] : NULL,
  188. global_auth);
  189. /* Evaluate the cachable value */
  190. if (local_cachable < *cachable) {
  191. /* Take the minimum value */
  192. *cachable = local_cachable;
  193. }
  194. /* Evaluate the return code */
  195. switch (result) {
  196. case LAS_EVAL_TRUE:
  197. if (expr->true_idx < 0)
  198. return (expr->true_idx);
  199. else {
  200. expr_index = expr->true_idx;
  201. expr = &ace->expr_arry[expr->true_idx];
  202. }
  203. break;
  204. case LAS_EVAL_FALSE:
  205. if (expr->false_idx < 0)
  206. return (expr->false_idx);
  207. else {
  208. expr_index = expr->false_idx;
  209. expr = &ace->expr_arry[expr->false_idx];
  210. }
  211. break;
  212. default:
  213. return (result);
  214. }
  215. }
  216. }
  217. int
  218. ACL_EvalDestroyContext(ACLListCache_t *cache)
  219. {
  220. ACLAceEntry_t *cur_ace, *next_ace;
  221. ACLAceNumEntry_t *cur_num_p, *next_num_p;
  222. if (!cache)
  223. return 0;
  224. PR_HashTableDestroy(cache->Table);
  225. cache->Table = NULL;
  226. cur_ace = cache->acelist;
  227. cache->acelist = NULL;
  228. while (cur_ace) {
  229. if (cur_ace->autharray)
  230. PERM_FREE(cur_ace->autharray);
  231. if ((cur_ace->global_auth) &&
  232. (cur_ace->acep->expr_type == ACL_EXPR_TYPE_AUTH))
  233. PListDestroy(cur_ace->global_auth);
  234. next_ace = cur_ace->next;
  235. PERM_FREE(cur_ace);
  236. cur_ace = next_ace;
  237. }
  238. cur_num_p = cache->chain_head;
  239. cache->chain_head = NULL;
  240. while (cur_num_p) {
  241. next_num_p = cur_num_p->chain;
  242. PERM_FREE(cur_num_p);
  243. cur_num_p = next_num_p;
  244. }
  245. PERM_FREE(cache);
  246. return 0;
  247. }
  248. /* ACLEvalBuildContext
  249. * Builds three structures:
  250. * Table - A hash table of all access rights referenced by any ACE in any
  251. * of the ACLs in this list. Each hash entry then has a list of
  252. * the relevant ACEs, in the form of indexes to the ACE linked
  253. * list.
  254. * ACE List - A linked list of all the ACEs in the proper evaluation order.
  255. *
  256. * For concurrency control, the caller must call ACL_CritEnter()
  257. */
  258. int
  259. ACLEvalBuildContext(
  260. NSErr_t *errp,
  261. ACLEvalHandle_t *acleval)
  262. {
  263. ACLHandle_t *acl;
  264. ACLExprHandle_t *ace;
  265. int ace_cnt = -1;
  266. ACLAceEntry_t *acelast = NULL, *new_ace;
  267. ACLAceNumEntry_t *entry, *temp_entry;
  268. char **argp;
  269. ACLListCache_t *cache;
  270. ACLWrapper_t *wrapper;
  271. PList_t curauthplist=NULL, absauthplist=NULL;
  272. int i, rv;
  273. ACLExprEntry_t *expr;
  274. PList_t authplist;
  275. /* Allocate the cache context and link it into the ACLListHandle */
  276. cache = (ACLListCache_t *)PERM_CALLOC(sizeof(ACLListCache_t));
  277. if (cache == NULL) {
  278. nserrGenerate(errp, ACLERRNOMEM, ACLERR4010, ACL_Program, 0);
  279. goto error;
  280. }
  281. /* Allocate the access rights hash table */
  282. cache->Table = PR_NewHashTable(0,
  283. PR_HashString,
  284. PR_CompareStrings,
  285. PR_CompareValues,
  286. &ACLPermAllocOps,
  287. NULL);
  288. if (cache->Table == NULL) {
  289. nserrGenerate(errp, ACLERRNOMEM, ACLERR4000, ACL_Program, 1,
  290. XP_GetAdminStr(DBT_EvalBuildContextUnableToCreateHash));
  291. goto error;
  292. }
  293. wrapper = acleval->acllist->acl_list_head;
  294. /* Loop through all the ACLs in the list */
  295. while (wrapper)
  296. {
  297. acl = wrapper->acl;
  298. ace = acl->expr_list_head;
  299. while (ace) /* Loop through all the ACEs in this ACL */
  300. {
  301. /* allocate a new ace list entry and link it in to the ordered
  302. * list.
  303. */
  304. new_ace = (ACLAceEntry_t *)PERM_CALLOC(sizeof(ACLAceEntry_t));
  305. if (new_ace == (ACLAceEntry_t *)NULL) {
  306. nserrGenerate(errp, ACLERRNOMEM, ACLERR4020, ACL_Program, 1,
  307. XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAceEntry));
  308. goto error;
  309. }
  310. new_ace->acep = ace;
  311. ace_cnt++;
  312. if (cache->acelist == NULL)
  313. cache->acelist = acelast = new_ace;
  314. else {
  315. if(acelast)
  316. acelast->next = new_ace;
  317. acelast = new_ace;
  318. new_ace->acep = ace;
  319. }
  320. new_ace->next = NULL;
  321. argp = ace->expr_argv;
  322. switch (ace->expr_type)
  323. {
  324. case ACL_EXPR_TYPE_ALLOW:
  325. case ACL_EXPR_TYPE_DENY:
  326. /* Add this ACE to the appropriate entries in the access rights
  327. * hash table
  328. */
  329. while (*argp)
  330. {
  331. entry = (ACLAceNumEntry_t *)PERM_CALLOC(sizeof(ACLAceNumEntry_t));
  332. if (entry == (ACLAceNumEntry_t *)NULL) {
  333. nserrGenerate(errp, ACLERRNOMEM, ACLERR4030, ACL_Program, 1,
  334. XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAceEntry));
  335. goto error;
  336. }
  337. if (cache->chain_head == NULL)
  338. cache->chain_head = cache->chain_tail = entry;
  339. else {
  340. cache->chain_tail->chain = entry;
  341. cache->chain_tail = entry;
  342. }
  343. entry->acenum = ace_cnt;
  344. /*
  345. * OK to call PL_HasTableLookup() even though it mods
  346. * the Table as this routine is called in critical section.
  347. */
  348. temp_entry = (ACLAceNumEntry_t *)PL_HashTableLookup(cache->Table, *argp);
  349. /* the first ACE for this right? */
  350. if (temp_entry) {
  351. /* Link it in at the end */
  352. while (temp_entry->next) {
  353. temp_entry = temp_entry->next;
  354. }
  355. temp_entry->next = entry;
  356. } else /* just link it in */
  357. PR_HashTableAdd(cache->Table, *argp, entry);
  358. argp++;
  359. }
  360. /* See if any of the clauses require authentication. */
  361. if (curauthplist) {
  362. for (i = 0; i < ace->expr_term_index; i++) {
  363. expr = &ace->expr_arry[i];
  364. rv = PListFindValue(curauthplist, expr->attr_name,
  365. NULL, &authplist);
  366. if (rv > 0) {
  367. /* First one for this ACE? */
  368. if (!new_ace->autharray) {
  369. new_ace->autharray = (PList_t *)PERM_CALLOC(sizeof(PList_t) * ace->expr_term_index);
  370. if (!new_ace->autharray) {
  371. nserrGenerate(errp, ACLERRNOMEM, ACLERR4040, ACL_Program, 1,
  372. XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAuthPointerArray));
  373. goto error;
  374. }
  375. }
  376. new_ace->autharray[i] = authplist;
  377. }
  378. }
  379. }
  380. break;
  381. case ACL_EXPR_TYPE_AUTH:
  382. /* Allocate the running auth tables if none yet */
  383. if (!curauthplist) {
  384. curauthplist = PListNew(NULL);
  385. if (!curauthplist) {
  386. nserrGenerate(errp, ACLERRNOMEM, ACLERR4050, ACL_Program, 1,
  387. XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAuthPlist));
  388. goto error;
  389. }
  390. absauthplist = PListNew(NULL);
  391. if (!absauthplist) {
  392. nserrGenerate(errp, ACLERRNOMEM, ACLERR4050, ACL_Program, 1,
  393. XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAuthPlist));
  394. goto error;
  395. }
  396. } else { /* duplicate the existing auth table */
  397. curauthplist = PListDuplicate(curauthplist, NULL, 0);
  398. if (!curauthplist) {
  399. nserrGenerate(errp, ACLERRNOMEM, ACLERR4050, ACL_Program, 1,
  400. XP_GetAdminStr(DBT_EvalBuildContextUnableToAllocAuthPlist));
  401. goto error;
  402. }
  403. }
  404. /* For each listed attribute */
  405. while (*argp) {
  406. /* skip any attributes that were absoluted */
  407. if (PListFindValue(absauthplist, *argp, NULL, NULL) < 0){
  408. /* Save pointer to the property list */
  409. PListInitProp(curauthplist, 0, *argp, ace->expr_auth, ace->expr_auth);
  410. if (IS_ABSOLUTE(ace->expr_flags))
  411. PListInitProp(absauthplist, 0, *argp, NULL, NULL);
  412. }
  413. argp++;
  414. }
  415. break;
  416. case ACL_EXPR_TYPE_RESPONSE:
  417. (void) ACL_ExprGetDenyWith(NULL, ace, &cache->deny_type,
  418. &cache->deny_response);
  419. break;
  420. default:
  421. PR_ASSERT(0);
  422. } /* switch expr_type */
  423. new_ace->global_auth = curauthplist;
  424. ace = ace->expr_next;
  425. } /* while (ace) */
  426. /* Next ACL please */
  427. wrapper = wrapper->wrap_next;
  428. }
  429. if (absauthplist)
  430. PListDestroy(absauthplist);
  431. /* This must be done last to avoid a race in initialization */
  432. acleval->acllist->cache = (void *)cache;
  433. /* covscan false positive acelast is linked in the cache */
  434. /* coverity[leaked_storage] */
  435. return 0;
  436. error:
  437. if (curauthplist)
  438. PListDestroy(curauthplist);
  439. if (absauthplist)
  440. PListDestroy(absauthplist);
  441. if (cache) {
  442. ACL_EvalDestroyContext(cache);
  443. }
  444. acleval->acllist->cache = NULL;
  445. /* covscan false positive acelast is linked in the cache */
  446. /* coverity[leaked_storage] */
  447. return ACL_RES_ERROR;
  448. }
  449. /* ACL_InvalidateSubjectPList
  450. * Given a new authentication plist, enumerate the plist and for each
  451. * key in the plist, search for the matching key in the subject plist
  452. * and delete any matches. E.g. "user", "group".
  453. */
  454. void
  455. ACL_InvalidateSubjectPList(char *attr, const void *value, void *user_data)
  456. {
  457. PList_t subject = (PList_t)user_data;
  458. PListDeleteProp(subject, 0, attr);
  459. return;
  460. }
  461. NSAPI_PUBLIC int ACL_SetDefaultResult (NSErr_t *errp,
  462. ACLEvalHandle_t *acleval,
  463. int result)
  464. {
  465. int rv;
  466. switch(result) {
  467. case ACL_RES_ALLOW:
  468. case ACL_RES_DENY:
  469. case ACL_RES_FAIL:
  470. case ACL_RES_INVALID:
  471. acleval->default_result = result;
  472. rv = 0;
  473. break;
  474. default:
  475. rv = -1;
  476. }
  477. return rv;
  478. }
  479. NSAPI_PUBLIC int ACL_GetDefaultResult (ACLEvalHandle_t *acleval)
  480. {
  481. return acleval->default_result;
  482. }
  483. /* ACL_INTEvalTestRights
  484. * INPUT
  485. * *errp The usual error context stack
  486. * *acleval A list of ACLs
  487. * **rights An array of strings listing the requested rights
  488. * **map_generic An array of strings listing the specific rights
  489. * that map from the generic rights.
  490. * OUTPUT
  491. * **deny_type bong file type passed on the way back out
  492. * **deny_response bong file pathname passed on the way back out
  493. * **acl_tag Name of the ACL that denies access
  494. * *expr_num ACE number within the denying ACL
  495. * *cachable Is the result cachable?
  496. */
  497. static int
  498. ACL_INTEvalTestRights(
  499. NSErr_t *errp,
  500. ACLEvalHandle_t *acleval,
  501. const char **rights,
  502. const char **map_generic,
  503. char **deny_type,
  504. char **deny_response,
  505. char **acl_tag,
  506. int *expr_num,
  507. ACLCachable_t *cachable)
  508. {
  509. struct rights_ent {
  510. char right[64]; /* lowercase-ed rights string */
  511. int result; /* Interim result value */
  512. int absolute; /* ACE with absolute keyword */
  513. int count; /* # specific + generic rights */
  514. ACLAceNumEntry_t *acelist[ACL_MAX_GENERIC+1];
  515. /* List of relevant ACEs */
  516. };
  517. struct rights_ent *rarray_p;
  518. struct rights_ent rights_arry[ACL_MAX_TEST_RIGHTS];
  519. ACLAceNumEntry_t *alllist; /* List of ACEs for "all" rights */
  520. ACLAceEntry_t *cur_ace;
  521. ACLListCache_t *cache;
  522. int rights_cnt = 0;
  523. int prev_acenum, cur_acenum;
  524. int i, j, right_num, delta;
  525. ACLCachable_t ace_cachable;
  526. int result;
  527. int absolute = 0;
  528. int skipflag;
  529. int g_num; /* index into the generic rights array. */
  530. const char **g_rights;
  531. PList_t global_auth=NULL;
  532. int allow_error = 0;
  533. int allow_absolute = 0;
  534. char *allow_tag = NULL;
  535. int allow_num = 0;
  536. int default_result = ACL_GetDefaultResult(acleval);
  537. *acl_tag = NULL;
  538. *expr_num = 0;
  539. *cachable = ACL_INDEF_CACHABLE;
  540. /*
  541. * The acleval contains the list of acis we are asking about.
  542. * In our case it's always of length 1.
  543. * The acleval is a per aclpb structure but
  544. * the acllist is a global structure derived from the global
  545. * aci cache--so access to acllist is multi-threaded.
  546. * Hence, for example the use of the "read-only" hash
  547. * lookup routines in this function--ACL_EvalTestRights()
  548. * is called in a "reader only context" so this code is therefore
  549. * thread-safe.
  550. */
  551. if (acleval->acllist == ACL_LIST_NO_ACLS) return ACL_RES_ALLOW;
  552. /* Build up the access right - indexed structures */
  553. if (acleval->acllist->cache == NULL) {
  554. ACL_CritEnter();
  555. if (acleval->acllist->cache == NULL) { /* Check again */
  556. if (ACLEvalBuildContext(errp, acleval) == ACL_RES_ERROR) {
  557. nserrGenerate(errp, ACLERRINTERNAL, ACLERR4110, ACL_Program,
  558. 1, XP_GetAdminStr(DBT_EvalTestRightsEvalBuildContextFailed));
  559. ACL_CritExit();
  560. return ACL_RES_ERROR;
  561. }
  562. }
  563. ACL_CritExit();
  564. }
  565. cache = (ACLListCache_t *)acleval->acllist->cache;
  566. *deny_response = cache->deny_response;
  567. *deny_type = cache->deny_type;
  568. /* For the list of rights requested, get back the list of relevant
  569. * ACEs. If we want
  570. * to alter the precedence of allow/deny, this would be a good
  571. * place to do it.
  572. */
  573. while (*rights && rights_cnt < ACL_MAX_TEST_RIGHTS)
  574. {
  575. rarray_p = &rights_arry[rights_cnt];
  576. /* Initialize the rights array entry */
  577. strcpy(&rarray_p->right[0], *rights);
  578. makelower(&rarray_p->right[0]);
  579. rarray_p->result = default_result;
  580. rarray_p->absolute = 0;
  581. rarray_p->count = 1; // There's always the specific right
  582. /* Locate the list of ACEs that apply to the right */
  583. rarray_p->acelist[0] =
  584. (ACLAceNumEntry_t *)ACL_HashTableLookup_const(cache->Table, rarray_p->right);
  585. /* See if the requested right also maps back to a generic right and
  586. * if so, locate the acelist for it as well.
  587. */
  588. if (map_generic)
  589. {
  590. for (g_rights=map_generic, g_num=0; *g_rights; g_rights++, g_num++)
  591. {
  592. if (strstr(*g_rights, rarray_p->right)) {
  593. // Add it to our acelist, but skip 0 'cause that's the
  594. // specific right.
  595. rarray_p->acelist[rarray_p->count++] =
  596. (ACLAceNumEntry_t *)ACL_HashTableLookup_const(cache->Table,
  597. (char *)generic_rights[g_num]);
  598. PR_ASSERT (rarray_p->count < ACL_MAX_GENERIC);
  599. }
  600. }
  601. }
  602. rights_cnt++;
  603. rights++;
  604. PR_ASSERT (rights_cnt < ACL_MAX_TEST_RIGHTS);
  605. }
  606. /* Special case - look for an entry that applies to "all" rights */
  607. alllist = (ACLAceNumEntry_t *)ACL_HashTableLookup_const(cache->Table, "all");
  608. /* Ok, we've now got a list of relevant ACEs. Now evaluate things. */
  609. prev_acenum = -1;
  610. cur_ace = cache->acelist;
  611. /* Loop through the relevant ACEs for the requested rights */
  612. while (TRUE)
  613. {
  614. cur_acenum = 10000; /* Pick a really high num so we lose */
  615. /* Find the lowest ACE among the rights lists */
  616. for (i=0; i<rights_cnt; i++) {
  617. rarray_p = &rights_arry[i];
  618. if (rarray_p->absolute) continue; // This right doesn't matter
  619. for (j=0; j<rarray_p->count; j++) {
  620. if ((rarray_p->acelist[j] != NULL) &&
  621. (rarray_p->acelist[j]->acenum < cur_acenum)) {
  622. cur_acenum = rarray_p->acelist[j]->acenum;
  623. }
  624. }
  625. }
  626. /* Special case - look for the "all" rights ace list and see if its
  627. * the lowest of all.
  628. */
  629. if (alllist && (alllist->acenum < cur_acenum))
  630. cur_acenum = alllist->acenum;
  631. /* If no new ACEs then we're done - evaluate the rights list */
  632. if (cur_acenum == 10000)
  633. break;
  634. /* Locate that ACE and evaluate it. We have to step through the
  635. * linked list of ACEs to find it.
  636. */
  637. if (prev_acenum == -1)
  638. delta = cur_acenum;
  639. else
  640. delta = cur_acenum - prev_acenum;
  641. for (i=0; i<delta; i++)
  642. cur_ace = cur_ace->next;
  643. if (global_auth && global_auth != cur_ace->global_auth) {
  644. /* We must enumerate the auth_info plist and remove entries for
  645. * each attribute from the subject property list.
  646. */
  647. PListEnumerate(cur_ace->global_auth, ACL_InvalidateSubjectPList,
  648. acleval->subject);
  649. }
  650. global_auth = cur_ace->global_auth;
  651. result = ACLEvalAce(errp, acleval, cur_ace->acep, &ace_cachable,
  652. cur_ace->autharray, cur_ace->global_auth);
  653. /* Evaluate the cachable value */
  654. if (ace_cachable < *cachable) {
  655. /* Take the minimum value */
  656. *cachable = ace_cachable;
  657. }
  658. /* Under certain circumstances, no matter what happens later,
  659. * the current result is not gonna change.
  660. */
  661. if ((result != LAS_EVAL_TRUE) && (result != LAS_EVAL_FALSE)) {
  662. if (cur_ace->acep->expr_type != ACL_EXPR_TYPE_ALLOW) {
  663. if (allow_error) {
  664. *acl_tag = allow_tag;
  665. *expr_num = allow_num;
  666. return (allow_error);
  667. } else {
  668. *acl_tag = cur_ace->acep->acl_tag;
  669. *expr_num = cur_ace->acep->expr_number;
  670. return (EvalToRes(result));
  671. }
  672. } else {
  673. /* If the error is on an allow statement, continue processing
  674. * and see if a subsequent allow works. If not, remember the
  675. * error and return it.
  676. */
  677. if (!allow_error) {
  678. allow_error = EvalToRes(result);
  679. allow_tag = cur_ace->acep->acl_tag;
  680. allow_num = cur_ace->acep->expr_number;
  681. }
  682. if (IS_ABSOLUTE(cur_ace->acep->expr_flags)) {
  683. allow_absolute = 1;
  684. }
  685. }
  686. }
  687. /* Now apply the result to the rights array. Look to see which rights'
  688. * acelist include the current one, or if the current one is on the
  689. * "all" rights ace list.
  690. */
  691. for (right_num=0; right_num<rights_cnt; right_num++)
  692. {
  693. rarray_p = &rights_arry[right_num];
  694. /* Have we fixated on a prior result? */
  695. if (rarray_p->absolute)
  696. continue;
  697. skipflag = 1;
  698. // Did this ace apply to this right?
  699. for (i=0; i<rarray_p->count; i++) {
  700. if ((rarray_p->acelist[i]) &&
  701. (rarray_p->acelist[i]->acenum == cur_acenum)) {
  702. rarray_p->acelist[i] = rarray_p->acelist[i]->next;
  703. skipflag = 0;
  704. }
  705. }
  706. /* This ace was on the "all" rights queue */
  707. if ((alllist) && (alllist->acenum == cur_acenum)) {
  708. skipflag = 0;
  709. }
  710. if (skipflag)
  711. continue; /* doesn't apply to this right */
  712. if (IS_ABSOLUTE(cur_ace->acep->expr_flags) && (result ==
  713. LAS_EVAL_TRUE)) {
  714. rarray_p->absolute = 1;
  715. absolute = 1;
  716. } else
  717. absolute = 0;
  718. switch (cur_ace->acep->expr_type) {
  719. case ACL_EXPR_TYPE_ALLOW:
  720. if (result == LAS_EVAL_TRUE) {
  721. rarray_p->result = ACL_RES_ALLOW;
  722. if (!allow_absolute) {
  723. /* A previous ALLOW error was superceded */
  724. allow_error = 0;
  725. }
  726. }
  727. else if (!*acl_tag) {
  728. *acl_tag = cur_ace->acep->acl_tag;
  729. *expr_num = cur_ace->acep->expr_number;
  730. }
  731. break;
  732. case ACL_EXPR_TYPE_DENY:
  733. if (result == LAS_EVAL_TRUE) {
  734. *acl_tag = cur_ace->acep->acl_tag;
  735. *expr_num = cur_ace->acep->expr_number;
  736. if (absolute) {
  737. if (allow_error) {
  738. *acl_tag = allow_tag;
  739. *expr_num = allow_num;
  740. return (allow_error);
  741. }
  742. return (ACL_RES_DENY);
  743. }
  744. rarray_p->result = ACL_RES_DENY;
  745. }
  746. break;
  747. default:
  748. /* a non-authorization ACE, just ignore */
  749. break;
  750. }
  751. }
  752. /* This ace was on the "all" rights queue */
  753. if ((alllist) && (alllist->acenum == cur_acenum)) {
  754. alllist = alllist->next;
  755. }
  756. /* If this is an absolute, check to see if all the rights
  757. * have already been fixed by this or previous absolute
  758. * statements. If so, we can compute the response without
  759. * evaluating any more of the ACL list.
  760. */
  761. if (absolute) {
  762. for (i=0; i<rights_cnt; i++) {
  763. /* Non absolute right, so skip this section */
  764. if (rights_arry[i].absolute == 0)
  765. break;
  766. /* This shouldn't be possible, but check anyway.
  767. * Any absolute non-allow result should already
  768. * have been returned earlier.
  769. */
  770. if (rights_arry[i].result != ACL_RES_ALLOW) {
  771. char result_str[16];
  772. sprintf(result_str, "%d", rights_arry[i].result);
  773. nserrGenerate(errp, ACLERRINTERNAL, ACLERR4100, ACL_Program, 3, XP_GetAdminStr(DBT_EvalTestRightsInterimAbsoluteNonAllowValue), rights[i], result_str);
  774. break;
  775. }
  776. if (i == (rights_cnt - 1))
  777. return ACL_RES_ALLOW;
  778. }
  779. }
  780. prev_acenum = cur_acenum;
  781. } /* Next ACE */
  782. /* Do an AND on the results for the individual rights */
  783. for (right_num=0; right_num<rights_cnt; right_num++)
  784. if (rights_arry[right_num].result != ACL_RES_ALLOW) {
  785. if (allow_error) {
  786. *acl_tag = allow_tag;
  787. *expr_num = allow_num;
  788. return (allow_error);
  789. }
  790. return (rights_arry[right_num].result);
  791. }
  792. return (ACL_RES_ALLOW);
  793. }
  794. /* ACL_CachableAclList
  795. * Returns 1 if the ACL list will always evaluate to ALLOW for http_get.
  796. */
  797. NSAPI_PUBLIC int
  798. ACL_CachableAclList(ACLListHandle_t *acllist)
  799. {
  800. ACLEvalHandle_t *acleval;
  801. char *bong;
  802. char *bong_type;
  803. char *acl_tag;
  804. int expr_num;
  805. int rv;
  806. static const char *rights[] = { "http_get", NULL };
  807. ACLCachable_t cachable=ACL_INDEF_CACHABLE;
  808. if (!acllist || acllist == ACL_LIST_NO_ACLS) {
  809. return 1;
  810. }
  811. acleval = ACL_EvalNew(NULL, NULL);
  812. ACL_EvalSetACL(NULL, acleval, acllist);
  813. rv = ACL_INTEvalTestRights(NULL, acleval, rights, http_generic,
  814. &bong_type, &bong, &acl_tag, &expr_num,
  815. &cachable);
  816. ACL_EvalDestroyNoDecrement(NULL, NULL, acleval);
  817. if (rv == ACL_RES_ALLOW && cachable == ACL_INDEF_CACHABLE) {
  818. return 1;
  819. }
  820. return 0;
  821. }
  822. NSAPI_PUBLIC int
  823. ACL_EvalTestRights(
  824. NSErr_t *errp,
  825. ACLEvalHandle_t *acleval,
  826. const char **rights,
  827. const char **map_generic,
  828. char **deny_type,
  829. char **deny_response,
  830. char **acl_tag,
  831. int *expr_num)
  832. {
  833. ACLCachable_t cachable;
  834. return (ACL_INTEvalTestRights(errp, acleval, rights, map_generic,
  835. deny_type, deny_response,
  836. acl_tag, expr_num, &cachable));
  837. }
  838. NSAPI_PUBLIC ACLEvalHandle_t *
  839. ACL_EvalNew(NSErr_t *errp, pool_handle_t *pool)
  840. {
  841. ACLEvalHandle_t *rv = ((ACLEvalHandle_t *)pool_calloc(pool, sizeof(ACLEvalHandle_t), 1));
  842. rv->default_result = ACL_RES_DENY;
  843. return rv;
  844. }
  845. NSAPI_PUBLIC void
  846. ACL_EvalDestroy(NSErr_t *errp, pool_handle_t *pool, ACLEvalHandle_t *acleval)
  847. {
  848. if (!acleval->acllist || acleval->acllist == ACL_LIST_NO_ACLS)
  849. return;
  850. PR_ASSERT(acleval->acllist->ref_count > 0);
  851. ACL_CritEnter();
  852. PR_ASSERT(ACL_CritHeld());
  853. if (--acleval->acllist->ref_count == 0) {
  854. if (ACL_LIST_IS_STALE(acleval->acllist)) {
  855. ACL_ListDestroy(errp, acleval->acllist);
  856. }
  857. }
  858. ACL_CritExit();
  859. pool_free(pool, acleval);
  860. }
  861. NSAPI_PUBLIC void
  862. ACL_EvalDestroyNoDecrement(NSErr_t *errp, pool_handle_t *pool, ACLEvalHandle_t *acleval)
  863. {
  864. /*if (!acleval->acllist || acleval->acllist == ACL_LIST_NO_ACLS)
  865. return; */
  866. /* olga: we need to free acleval unconditionally to avoid memory leaks */
  867. if (acleval)
  868. pool_free(pool, acleval);
  869. }
  870. NSAPI_PUBLIC int
  871. ACL_ListDecrement(NSErr_t *errp, ACLListHandle_t *acllist)
  872. {
  873. if (!acllist || acllist == ACL_LIST_NO_ACLS)
  874. return 0;
  875. PR_ASSERT(ACL_AssertAcllist(acllist));
  876. ACL_CritEnter();
  877. PR_ASSERT(ACL_CritHeld());
  878. if (--acllist->ref_count == 0) {
  879. if (ACL_LIST_IS_STALE(acllist)) {
  880. ACL_ListDestroy(errp, acllist);
  881. }
  882. }
  883. ACL_CritExit();
  884. return 0;
  885. }
  886. NSAPI_PUBLIC int
  887. ACL_EvalSetACL(NSErr_t *errp, ACLEvalHandle_t *acleval, ACLListHandle_t *acllist)
  888. {
  889. PR_ASSERT(ACL_AssertAcllist(acllist));
  890. acleval->acllist = acllist;
  891. return(0);
  892. }
  893. NSAPI_PUBLIC int
  894. ACL_EvalSetSubject(NSErr_t *errp, ACLEvalHandle_t *acleval, PList_t subject)
  895. {
  896. acleval->subject = subject;
  897. return 0;
  898. }
  899. NSAPI_PUBLIC PList_t
  900. ACL_EvalGetSubject(NSErr_t *errp, ACLEvalHandle_t *acleval)
  901. {
  902. return (acleval->subject);
  903. }
  904. NSAPI_PUBLIC int
  905. ACL_EvalSetResource(NSErr_t *errp, ACLEvalHandle_t *acleval, PList_t resource)
  906. {
  907. acleval->resource = resource;
  908. return 0;
  909. }
  910. NSAPI_PUBLIC PList_t
  911. ACL_EvalGetResource(NSErr_t *errp, ACLEvalHandle_t *acleval)
  912. {
  913. return (acleval->resource);
  914. }