oneeval.cpp 30 KB

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