aclbuild.cpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360
  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. * END COPYRIGHT BLOCK **/
  6. /*
  7. * Description (aclbuild.c)
  8. *
  9. * This module provides functions for building Access Control List
  10. * (ACL) structures in memory.
  11. *
  12. */
  13. #include <assert.h>
  14. #include "base/systems.h"
  15. #include "netsite.h"
  16. #include "libaccess/nsauth.h"
  17. #include "libaccess/nsuser.h"
  18. #include "libaccess/nsgroup.h"
  19. #include "libaccess/nsadb.h"
  20. #include "libaccess/aclerror.h"
  21. #include "libaccess/aclstruct.h"
  22. #include "libaccess/aclbuild.h"
  23. #include "libaccess/aclparse.h"
  24. #include "libaccess/acleval.h"
  25. #include "libaccess/usi.h"
  26. char * ACL_Program = "NSACL"; /* ACL facility name */
  27. /*
  28. * Description (accCreate)
  29. *
  30. * This function creates a new access control context, which
  31. * provides context information for a set of ACL definitions.
  32. * The caller also provides a handle for a symbol table to be
  33. * used to store definitions of ACL and rights names.
  34. *
  35. * Arguments:
  36. *
  37. * errp - error frame list pointer (may be null)
  38. * stp - symbol table handle (may be null)
  39. * pacc - pointer to returned context handle
  40. *
  41. * Returns:
  42. *
  43. * If the context is created successfully, the return value is zero.
  44. * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h),
  45. * and an error frame will be generated if an error list is provided.
  46. */
  47. int accCreate(NSErr_t * errp, void * stp, ACContext_t **pacc)
  48. {
  49. ACContext_t * acc; /* pointer to new context */
  50. int rv; /* result value */
  51. int eid; /* error id */
  52. *pacc = 0;
  53. /* Do we need to create a symbol table? */
  54. if (stp == 0) {
  55. /* Yes, create a symbol table for ACL, rights, etc. names */
  56. rv = symTableNew(&stp);
  57. if (rv < 0) goto err_nomem1;
  58. }
  59. /* Allocate the context structure */
  60. acc = (ACContext_t *)MALLOC(sizeof(ACContext_t));
  61. if (acc == 0) goto err_nomem2;
  62. /* Initialize it */
  63. acc->acc_stp = stp;
  64. acc->acc_acls = 0;
  65. acc->acc_rights = 0;
  66. acc->acc_refcnt = 0;
  67. *pacc = acc;
  68. return 0;
  69. err_nomem1:
  70. rv = ACLERRNOMEM;
  71. eid = ACLERR3000;
  72. goto err_ret;
  73. err_nomem2:
  74. rv = ACLERRNOMEM;
  75. eid = ACLERR3020;
  76. err_ret:
  77. nserrGenerate(errp, rv, eid, ACL_Program, 0);
  78. return rv;
  79. }
  80. /*
  81. * Description (accDestroy)
  82. *
  83. * This function destroys a set of ACL data structures referenced
  84. * by a specified ACContext_t structure, including the ACContext_t
  85. * itself.
  86. *
  87. * Arguments:
  88. *
  89. * acc - pointer to ACContext_t structure
  90. * flags - bit flags (unused - must be zero)
  91. */
  92. void accDestroy(ACContext_t * acc, int flags)
  93. {
  94. ACL_t * acl;
  95. if (acc != 0) {
  96. /*
  97. * First destroy all ACLs and any unnamed structures they reference.
  98. * Note that aclDestroy() modifies the acc_acls list.
  99. */
  100. while ((acl = acc->acc_acls) != 0) {
  101. aclDelete(acl);
  102. }
  103. /* If there's a symbol table, destroy everything it references */
  104. if (acc->acc_stp != 0) {
  105. symTableEnumerate(acc->acc_stp, 0, accDestroySym);
  106. /* Destroy the symbol table itself */
  107. symTableDestroy(acc->acc_stp, 0);
  108. }
  109. /* Free the ACContext_t structure */
  110. FREE(acc);
  111. }
  112. }
  113. /*
  114. * Description (accDestroySym)
  115. *
  116. * This function is called to destroy the data structure associated
  117. * with a specified Symbol_t symbol table entry. It examines the
  118. * type of the symbol and calls the appropriate destructor.
  119. *
  120. * Arguments:
  121. *
  122. * sym - pointer to symbol table entry
  123. * argp - unused - must be zero
  124. *
  125. * Returns:
  126. *
  127. * The return value is SYMENUMREMOVE.
  128. */
  129. int accDestroySym(Symbol_t * sym, void * argp)
  130. {
  131. switch (sym->sym_type) {
  132. case ACLSYMACL: /* ACL */
  133. aclDestroy((ACL_t *)sym);
  134. break;
  135. case ACLSYMRIGHT: /* access right */
  136. {
  137. RightDef_t * rdp = (RightDef_t *)sym;
  138. if (rdp->rd_sym.sym_name != 0) {
  139. FREE(rdp->rd_sym.sym_name);
  140. }
  141. FREE(rdp);
  142. }
  143. break;
  144. case ACLSYMRDEF: /* access rights list */
  145. aclRightSpecDestroy((RightSpec_t *)sym);
  146. break;
  147. case ACLSYMREALM: /* realm name */
  148. aclRealmSpecDestroy((RealmSpec_t *)sym);
  149. break;
  150. case ACLSYMHOST: /* host specifications */
  151. aclHostSpecDestroy((HostSpec_t *)sym);
  152. break;
  153. case ACLSYMUSER: /* user/group list */
  154. aclUserSpecDestroy((UserSpec_t *)sym);
  155. break;
  156. }
  157. return SYMENUMREMOVE;
  158. }
  159. /*
  160. * Description (accReadFile)
  161. *
  162. * This function reads a specfied file containing ACL definitions
  163. * and creates data structures in memory to represent the ACLs.
  164. * The caller may provide a pointer to an existing ACContext_t
  165. * structure which will serve as the root of the ACL structures,
  166. * or else a new one will be created.
  167. *
  168. * Arguments:
  169. *
  170. * errp - error frame list pointer (may be null)
  171. * aclfile - pointer to the ACL filename string
  172. * pacc - value/result ACContext_t
  173. *
  174. * Returns:
  175. *
  176. * If the ACL file is read successfully, the return value is zero.
  177. * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h),
  178. * and an error frame will be generated if an error list is provided.
  179. */
  180. int accReadFile(NSErr_t * errp, char * aclfile, ACContext_t **pacc)
  181. {
  182. ACContext_t * acc = *pacc; /* pointer to ACL root structure */
  183. ACLFile_t * acf = 0; /* pointer to ACL file handle */
  184. void * stp = 0; /* ACL symbol table handle */
  185. int rv; /* result value */
  186. int eid; /* error id value */
  187. /* Initialize the ACL parser */
  188. rv = aclParseInit();
  189. if (rv < 0) goto err_init;
  190. /* Do we need to create a new ACContext_t structure? */
  191. if (acc == 0) {
  192. /* Yes, create a symbol table for ACL, rights, etc. names */
  193. rv = symTableNew(&stp);
  194. if (rv < 0) goto err_crsym;
  195. /* Create a root structure for the ACLs, including the symbol table */
  196. rv = accCreate(errp, stp, &acc);
  197. if (rv < 0) goto err_ret2;
  198. }
  199. /* Open the ACL definition file */
  200. rv = aclFileOpen(errp, aclfile, 0, &acf);
  201. if (rv < 0) goto err_ret3;
  202. /* Parse the ACL definitions, building ACL structures in memory */
  203. rv = aclACLParse(errp, acf, acc, 0);
  204. if (rv < 0) goto err_ret4;
  205. aclFileClose(acf, 0);
  206. if (pacc) *pacc = acc;
  207. return rv;
  208. err_init:
  209. eid = ACLERR3100;
  210. goto err_ret;
  211. err_crsym:
  212. eid = ACLERR3120;
  213. rv = ACLERRNOMEM;
  214. goto err_ret;
  215. err_ret4:
  216. aclFileClose(acf, 0);
  217. err_ret3:
  218. /* Destroy the ACContext_t if we just created it */
  219. if (acc != *pacc) {
  220. accDestroy(acc, 0);
  221. }
  222. goto err_ret;
  223. err_ret2:
  224. symTableDestroy(stp, 0);
  225. err_ret:
  226. return rv;
  227. }
  228. /*
  229. * Description (aclAuthDNSAdd)
  230. *
  231. * This function adds a DNS name specification to the DNS filter
  232. * associated with a given host list. The DNS name specification is
  233. * either a fully-qualified domain name or a domain name suffix,
  234. * indicated by a leading ".", e.g. (".mcom.com"). The name
  235. * components included in a suffix must be complete. For example,
  236. * ".scape.com" will not match names ending in ".netscape.com".
  237. *
  238. * Arguments:
  239. *
  240. * hspp - pointer to host list pointer
  241. * dnsspec - DNS name or suffix string pointer
  242. * fqdn - non-zero if dnsspec is fully qualified
  243. *
  244. * Returns:
  245. *
  246. * If successful, the return code is zero.
  247. * An error is indicated by a negative return code (ACLERRxxxx
  248. * - see aclerror.h).
  249. */
  250. int aclAuthDNSAdd(HostSpec_t **hspp, char * dnsspec, int fqdn)
  251. {
  252. HostSpec_t * hsp; /* host list pointer */
  253. void * table; /* access control hash table pointer */
  254. Symbol_t * sym; /* hash table entry pointer */
  255. int rv; /* result value */
  256. fqdn = (fqdn) ? 1 : 0;
  257. /* Create the HostSpec_t if it doesn't exist */
  258. hsp = *hspp;
  259. if (hsp == 0) {
  260. hsp = (HostSpec_t *)MALLOC(sizeof(HostSpec_t));
  261. if (hsp == 0) goto err_nomem;
  262. memset((void *)hsp, 0, sizeof(HostSpec_t));
  263. hsp->hs_sym.sym_type = ACLSYMHOST;
  264. }
  265. /* Get pointer to hash table used for DNS filter */
  266. table = hsp->hs_host.inh_dnf.dnf_hash;
  267. if (table == 0) {
  268. /* None there yet, so create one */
  269. rv = symTableNew(&table);
  270. if (rv < 0) goto punt;
  271. hsp->hs_host.inh_dnf.dnf_hash = table;
  272. }
  273. /* See if the DNS spec is already in the table */
  274. rv = symTableFindSym(table, dnsspec, fqdn, (void **)&sym);
  275. if (rv < 0) {
  276. if (rv != SYMERRNOSYM) goto punt;
  277. /* It's not there, so add it */
  278. sym = (Symbol_t *)MALLOC(sizeof(Symbol_t));
  279. sym->sym_name = STRDUP(dnsspec);
  280. sym->sym_type = fqdn;
  281. rv = symTableAddSym(table, sym, (void *)sym);
  282. if (rv < 0) goto err_nomem;
  283. }
  284. *hspp = hsp;
  285. punt:
  286. return rv;
  287. err_nomem:
  288. rv = ACLERRNOMEM;
  289. goto punt;
  290. }
  291. /*
  292. * Description (aclAuthIPAdd)
  293. *
  294. * This function adds an IP address specification to the IP filter
  295. * associated with a given host list. The IP address specification
  296. * consists of an IP host or network address and an IP netmask.
  297. * For host addresses the netmask value is 255.255.255.255.
  298. *
  299. * Arguments:
  300. *
  301. * hspp - pointer to host list pointer
  302. * ipaddr - IP host or network address
  303. * netmask - IP netmask value
  304. *
  305. * Returns:
  306. *
  307. * If successful, the return code is zero.
  308. * An error is indicated by a negative return code (ACLERRxxxx
  309. * - see aclerror.h).
  310. */
  311. int aclAuthIPAdd(HostSpec_t **hspp, IPAddr_t ipaddr, IPAddr_t netmask)
  312. {
  313. HostSpec_t * hsp; /* host list pointer */
  314. IPFilter_t * ipf; /* IP filter pointer */
  315. IPNode_t * ipn; /* current node pointer */
  316. IPNode_t * lastipn; /* last (lower) node pointer */
  317. IPLeaf_t * leaf; /* leaf node pointer */
  318. IPAddr_t bitmask; /* bit mask for current node */
  319. int lastbit; /* number of last bit set in netmask */
  320. int i; /* loop index */
  321. /* Create the HostSpec_t if it doesn't exist */
  322. hsp = *hspp;
  323. if (hsp == 0) {
  324. hsp = (HostSpec_t *)MALLOC(sizeof(HostSpec_t));
  325. if (hsp == 0) goto err_nomem;
  326. memset((void *)hsp, 0, sizeof(HostSpec_t));
  327. hsp->hs_sym.sym_type = ACLSYMHOST;
  328. }
  329. ipf = &hsp->hs_host.inh_ipf;
  330. /* If the filter doesn't have a root node yet, create it */
  331. if (ipf->ipf_tree == 0) {
  332. /* Allocate node */
  333. ipn = (IPNode_t *)MALLOC(sizeof(IPNode_t));
  334. if (ipn == 0) goto err_nomem;
  335. /* Initialize it to test bit 31, but without any descendants */
  336. ipn->ipn_type = IPN_NODE;
  337. ipn->ipn_bit = 31;
  338. ipn->ipn_parent = NULL;
  339. ipn->ipn_clear = NULL;
  340. ipn->ipn_set = NULL;
  341. ipn->ipn_masked = NULL;
  342. /* Set it as the root node in the radix tree */
  343. ipf->ipf_tree = ipn;
  344. }
  345. /* First we search the tree to see where this IP specification fits */
  346. lastipn = NULL;
  347. for (ipn = ipf->ipf_tree; (ipn != NULL) && (ipn->ipn_type == IPN_NODE); ) {
  348. /* Get a mask for the bit this node tests */
  349. bitmask = (IPAddr_t) 1<<ipn->ipn_bit;
  350. /* Save pointer to last internal node */
  351. lastipn = ipn;
  352. /* Is this a bit we care about? */
  353. if (bitmask & netmask) {
  354. /* Yes, get address of set or clear descendant pointer */
  355. ipn = (bitmask & ipaddr) ? ipn->ipn_set : ipn->ipn_clear;
  356. }
  357. else {
  358. /* No, get the address of the masked descendant pointer */
  359. ipn = ipn->ipn_masked;
  360. }
  361. }
  362. /* Did we end up at a leaf node? */
  363. if (ipn == NULL) {
  364. /*
  365. * No, well, we need to find a leaf node if possible. The
  366. * reason is that we need an IP address and netmask to compare
  367. * to the IP address and netmask we're inserting. We know that
  368. * they're the same up to the bit tested by the lastipn node,
  369. * but we need to know the *highest* order bit that's different.
  370. * Any leaf node below lastipn will do.
  371. */
  372. leaf = NULL;
  373. ipn = lastipn;
  374. while (ipn != NULL) {
  375. /* Look for any non-null child link of the current node */
  376. for (i = 0; i < IPN_NLINKS; ++i) {
  377. if (ipn->ipn_links[i]) break;
  378. }
  379. /*
  380. * Fail search for leaf if no non-null child link found.
  381. * This should only happen on the root node of the tree
  382. * when the tree is empty.
  383. */
  384. if (i >= IPN_NLINKS) {
  385. assert(ipn == ipf->ipf_tree);
  386. break;
  387. }
  388. /* Step to the child node */
  389. ipn = ipn->ipn_links[i];
  390. /* Is it a leaf? */
  391. if (ipn->ipn_type == IPN_LEAF) {
  392. /* Yes, search is over */
  393. leaf = (IPLeaf_t *)ipn;
  394. ipn = NULL;
  395. break;
  396. }
  397. }
  398. }
  399. else {
  400. /* Yes, loop terminated on a leaf node */
  401. assert(ipn->ipn_type == IPN_LEAF);
  402. leaf = (IPLeaf_t *)ipn;
  403. }
  404. /* Got a leaf yet? */
  405. if (leaf != NULL) {
  406. /* Combine the IP address and netmask differences */
  407. bitmask = (leaf->ipl_ipaddr ^ ipaddr) | (leaf->ipl_netmask ^ netmask);
  408. /* Are both the IP address and the netmask the same? */
  409. if (bitmask == 0) {
  410. /* Yes, duplicate entry */
  411. return 0;
  412. }
  413. /* Find the bit number of the first different bit */
  414. for (lastbit = 31;
  415. (bitmask & 0x80000000) == 0; --lastbit, bitmask <<= 1) ;
  416. /* Generate a bit mask with just that bit */
  417. bitmask = (IPAddr_t) (1 << lastbit);
  418. /*
  419. * Go up the tree from lastipn, looking for an internal node
  420. * that tests lastbit. Stop if we get to a node that tests
  421. * a higher bit number first.
  422. */
  423. for (ipn = lastipn, lastipn = (IPNode_t *)leaf;
  424. ipn != NULL; ipn = ipn->ipn_parent) {
  425. if (ipn->ipn_bit >= lastbit) {
  426. if (ipn->ipn_bit == lastbit) {
  427. /* Need to add a leaf off ipn node */
  428. lastipn = NULL;
  429. }
  430. break;
  431. }
  432. lastipn = ipn;
  433. }
  434. assert(ipn != NULL);
  435. }
  436. else {
  437. /* Just hang a leaf off the lastipn node if no leaf */
  438. ipn = lastipn;
  439. lastipn = NULL;
  440. lastbit = ipn->ipn_bit;
  441. }
  442. /*
  443. * If lastipn is not NULL at this point, the new leaf will hang
  444. * off an internal node inserted between the upper node, referenced
  445. * by ipn, and the lower node, referenced by lastipn. The lower
  446. * node may be an internal node or a leaf.
  447. */
  448. if (lastipn != NULL) {
  449. IPNode_t * parent = ipn; /* parent of the new node */
  450. assert((lastipn->ipn_type == IPN_LEAF) ||
  451. (ipn == lastipn->ipn_parent));
  452. /* Allocate space for the internal node */
  453. ipn = (IPNode_t *)MALLOC(sizeof(IPNode_t));
  454. if (ipn == NULL) goto err_nomem;
  455. ipn->ipn_type = IPN_NODE;
  456. ipn->ipn_bit = lastbit;
  457. ipn->ipn_parent = parent;
  458. ipn->ipn_clear = NULL;
  459. ipn->ipn_set = NULL;
  460. ipn->ipn_masked = NULL;
  461. bitmask = (IPAddr_t) (1 << lastbit);
  462. /*
  463. * The values in the leaf we found above determine which
  464. * descendant link of the new internal node will reference
  465. * the subtree that we just ascended.
  466. */
  467. if (leaf->ipl_netmask & bitmask) {
  468. if (leaf->ipl_ipaddr & bitmask) {
  469. ipn->ipn_set = lastipn;
  470. }
  471. else {
  472. ipn->ipn_clear = lastipn;
  473. }
  474. }
  475. else {
  476. ipn->ipn_masked = lastipn;
  477. }
  478. /* Allocate space for the new leaf */
  479. leaf = (IPLeaf_t *)MALLOC(sizeof(IPLeaf_t));
  480. if (leaf == NULL) {
  481. FREE((void *)ipn);
  482. goto err_nomem;
  483. }
  484. /* Insert internal node in tree */
  485. /* First the downward link from the parent to the new node */
  486. for (i = 0; i < IPN_NLINKS; ++i) {
  487. if (parent->ipn_links[i] == lastipn) {
  488. parent->ipn_links[i] = ipn;
  489. break;
  490. }
  491. }
  492. /* Then the upward link from the child (if it's not a leaf) */
  493. if (lastipn->ipn_type == IPN_NODE) {
  494. lastipn->ipn_parent = ipn;
  495. }
  496. }
  497. else {
  498. /* Allocate space for a leaf node only */
  499. leaf = (IPLeaf_t *)MALLOC(sizeof(IPLeaf_t));
  500. if (leaf == NULL) goto err_nomem;
  501. }
  502. /* Initialize the new leaf */
  503. leaf->ipl_type = IPN_LEAF;
  504. leaf->ipl_ipaddr = ipaddr;
  505. leaf->ipl_netmask = netmask;
  506. /*
  507. * Select the appropriate descendant link of the internal node
  508. * and point it at the new leaf.
  509. */
  510. bitmask = (IPAddr_t) (1 << ipn->ipn_bit);
  511. if (bitmask & netmask) {
  512. if (bitmask & ipaddr) {
  513. assert(ipn->ipn_set == NULL);
  514. ipn->ipn_set = (IPNode_t *)leaf;
  515. }
  516. else {
  517. assert(ipn->ipn_clear == NULL);
  518. ipn->ipn_clear = (IPNode_t *)leaf;
  519. }
  520. }
  521. else {
  522. assert(ipn->ipn_masked == NULL);
  523. ipn->ipn_masked = (IPNode_t *)leaf;
  524. }
  525. *hspp = hsp;
  526. /* Successful completion */
  527. return 0;
  528. err_nomem:
  529. return ACLERRNOMEM;
  530. }
  531. /*
  532. * Description (aclAuthNameAdd)
  533. *
  534. * This function adds a user or group to a given user list,
  535. * in the context of a specified ACL that is being created. The
  536. * name of the user or group is provided by the caller, and is
  537. * looked up in the authentication database associated with the
  538. * specified user list. The return value indicates whether the name
  539. * matched a user or group name, and whether the corresponding user
  540. * or group id was already present in the given user list.
  541. *
  542. * Arguments:
  543. *
  544. * errp - error frame list pointer (may be null)
  545. * usp - pointer to user list specification
  546. * rlm - pointer to current authentication realm
  547. * name - pointer to user or group name string
  548. *
  549. * Returns:
  550. *
  551. * The return value is zero if the name is not found in the
  552. * authentication database. If the name is found, the return value
  553. * is a positive value containing bit flags:
  554. *
  555. * AIF_GROUP - name matches a group name
  556. * AIF_USER - name matches a user name
  557. * AIF_DUP - name was already represented in the
  558. * specified user list
  559. *
  560. * An error is indicated by a negative return code (ACLERRxxxx
  561. * - see aclerror.h), and an error frame will be generated if
  562. * an error list is provided.
  563. */
  564. int aclAuthNameAdd(NSErr_t * errp, UserSpec_t * usp,
  565. Realm_t * rlm, char * name)
  566. {
  567. void * guoptr; /* group or user object pointer */
  568. int irv; /* insert result value */
  569. int eid; /* error id */
  570. int rv; /* result value */
  571. /* There must be a realm specified in order to handle users */
  572. if (rlm == 0) goto err_norealm;
  573. /* Open the authentication database if it's not already */
  574. if (rlm->rlm_authdb == 0) {
  575. if (rlm->rlm_aif == 0) {
  576. rlm->rlm_aif = &NSADB_AuthIF;
  577. }
  578. rv = (*rlm->rlm_aif->aif_open)(errp,
  579. rlm->rlm_dbname, 0, &rlm->rlm_authdb);
  580. if (rv < 0) goto err_open;
  581. }
  582. /* Look up the name in the authentication DB */
  583. rv = (*rlm->rlm_aif->aif_findname)(errp, rlm->rlm_authdb, name,
  584. (AIF_USER|AIF_GROUP), (void **)&guoptr);
  585. if (rv <= 0) {
  586. if (rv < 0) goto err_adb;
  587. /* The name was not found in the database */
  588. return 0;
  589. }
  590. /* The name was found. Was it a user name? */
  591. if (rv == AIF_USER) {
  592. /* Yes, add the user id to the user list */
  593. irv = usiInsert(&usp->us_user.uu_user, ((UserObj_t *)guoptr)->uo_uid);
  594. rv = ANA_USER;
  595. }
  596. else {
  597. /* No, must be a group name. Add group id to an_groups list. */
  598. irv = usiInsert(&usp->us_user.uu_group,
  599. ((GroupObj_t *)guoptr)->go_gid);
  600. rv = ANA_GROUP;
  601. }
  602. /* Examine the result of the insert operation */
  603. if (irv <= 0) {
  604. if (irv < 0) goto err_ins;
  605. /* Id was already in the list */
  606. rv |= ANA_DUP;
  607. }
  608. punt:
  609. return rv;
  610. err_norealm:
  611. eid = ACLERR3400;
  612. rv = ACLERRNORLM;
  613. nserrGenerate(errp, rv, eid, ACL_Program, 1, name);
  614. goto punt;
  615. err_open:
  616. eid = ACLERR3420;
  617. rv = ACLERROPEN;
  618. nserrGenerate(errp, rv, eid, ACL_Program,
  619. 2, rlm->rlm_dbname, system_errmsg());
  620. goto punt;
  621. err_adb:
  622. /* Error accessing authentication database. */
  623. eid = ACLERR3440;
  624. rv = ACLERRADB;
  625. nserrGenerate(errp, rv, eid, ACL_Program, 2, rlm->rlm_dbname, name);
  626. goto punt;
  627. err_ins:
  628. /* Error on insert operation. Must be lack of memory. */
  629. eid = ACLERR3460;
  630. rv = ACLERRNOMEM;
  631. nserrGenerate(errp, rv, eid, ACL_Program, 0);
  632. goto punt;
  633. }
  634. /*
  635. * Description (aclClientsDirCreate)
  636. *
  637. * This function allocates and initializes a new ACClients_t
  638. * ACL directive.
  639. *
  640. * Arguments:
  641. *
  642. * None.
  643. *
  644. * Returns:
  645. *
  646. * If successful, a pointer to the new ACClients_t is returned.
  647. * A shortage of dynamic memory is indicated by a null return value.
  648. */
  649. ACClients_t * aclClientsDirCreate()
  650. {
  651. ACClients_t * acd; /* pointer to new ACClients_t */
  652. acd = (ACClients_t *)MALLOC(sizeof(ACClients_t));
  653. if (acd != 0) {
  654. memset((void *)acd, 0, sizeof(ACClients_t));
  655. }
  656. return acd;
  657. }
  658. /*
  659. * Description (aclCreate)
  660. *
  661. * This function creates a new ACL root structure. The caller
  662. * specifies the name to be associated with the ACL. The ACL handle
  663. * returned by this function is passed to other functions in this
  664. * module when adding information to the ACL.
  665. *
  666. * Arguments:
  667. *
  668. * errp - error frame list pointer (may be null)
  669. * acc - pointer to an access control context
  670. * aclname - pointer to ACL name string
  671. * pacl - pointer to returned ACL handle
  672. *
  673. * Returns:
  674. *
  675. * The return value is zero if the ACL is created successfully.
  676. * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h),
  677. * and an error frame will be generated if an error list is provided.
  678. */
  679. int aclCreate(NSErr_t * errp, ACContext_t * acc, char * aclname, ACL_t **pacl)
  680. {
  681. ACL_t * acl; /* pointer to created ACL */
  682. int rv; /* result value */
  683. int eid; /* error id */
  684. *pacl = 0;
  685. /* Allocate the ACL_t structure */
  686. acl = (ACL_t *) MALLOC(sizeof(ACL_t));
  687. if (acl == 0) goto err_nomem;
  688. /* Initialize the structure */
  689. memset((void *)acl, 0, sizeof(ACL_t));
  690. acl->acl_sym.sym_name = STRDUP(aclname);
  691. acl->acl_sym.sym_type = ACLSYMACL;
  692. acl->acl_acc = acc;
  693. acl->acl_refcnt = 1;
  694. /* Add it to the symbol table for the specified context */
  695. rv = symTableAddSym(acc->acc_stp, &acl->acl_sym, (void *)acl);
  696. if (rv < 0) goto err_addsym;
  697. /* Add it to the list of ACLs for the specified context */
  698. acl->acl_next = acc->acc_acls;
  699. acc->acc_acls = acl;
  700. acc->acc_refcnt += 1;
  701. *pacl = acl;
  702. return 0;
  703. err_nomem:
  704. rv = ACLERRNOMEM;
  705. eid = ACLERR3200;
  706. nserrGenerate(errp, rv, eid, ACL_Program, 0);
  707. goto done;
  708. err_addsym:
  709. FREE(acl);
  710. rv = ACLERRDUPSYM;
  711. eid = ACLERR3220;
  712. nserrGenerate(errp, rv, eid, ACL_Program, 1, aclname);
  713. done:
  714. return rv;
  715. }
  716. /*
  717. * Description (aclDestroy)
  718. *
  719. * This function destroys an ACL structure and its sub-structures.
  720. * It does not free the ACContext_t referenced by the ACL.
  721. *
  722. * Arguments:
  723. *
  724. * acl - pointer to ACL_t structure
  725. */
  726. void aclDestroy(ACL_t * acl)
  727. {
  728. ACL_t **pacl; /* ACL list link pointer */
  729. ACDirective_t * acd; /* ACL directive pointer */
  730. ACDirective_t * nacd; /* next ACL directive pointer */
  731. /* Is there an ACContext_t structure? */
  732. if (acl->acl_acc != 0) {
  733. /* Remove this ACL from the list in the ACContext_t structure */
  734. for (pacl = &acl->acl_acc->acc_acls;
  735. *pacl != 0; pacl = &(*pacl)->acl_next) {
  736. if (*pacl == acl) {
  737. *pacl = acl->acl_next;
  738. acl->acl_acc->acc_refcnt -= 1;
  739. break;
  740. }
  741. }
  742. }
  743. /* Destroy each ACL directive */
  744. for (acd = acl->acl_dirf; acd != 0; acd = nacd) {
  745. nacd = acd->acd_next;
  746. aclDirectiveDestroy(acd);
  747. }
  748. /* Free the ACL rights list if it is unnamed */
  749. if ((acl->acl_rights != 0) && (acl->acl_rights->rs_sym.sym_name == 0)) {
  750. aclRightSpecDestroy(acl->acl_rights);
  751. }
  752. /* Free the ACL name string, if any */
  753. if (acl->acl_sym.sym_name != 0) {
  754. FREE(acl->acl_sym.sym_name);
  755. }
  756. /* Free the ACL itself */
  757. FREE(acl);
  758. }
  759. /*
  760. * Description (aclDelete)
  761. *
  762. * This function removes a specified ACL from the symbol table
  763. * associated with its ACL context, and then destroys the ACL
  764. * structure and any unnamed objects it references (other than
  765. * the ACL context).
  766. *
  767. * Arguments:
  768. *
  769. * acl - pointer to the ACL
  770. */
  771. void aclDelete(ACL_t * acl)
  772. {
  773. ACContext_t * acc = acl->acl_acc;
  774. if ((acc != 0) && (acl->acl_sym.sym_name != 0)) {
  775. symTableRemoveSym(acc->acc_stp, &acl->acl_sym);
  776. }
  777. aclDestroy(acl);
  778. }
  779. /*
  780. * Description (aclDirectiveAdd)
  781. *
  782. * This function adds a given directive to a specified ACL.
  783. *
  784. * Arguments:
  785. *
  786. * acl - pointer to the ACL
  787. * acd - pointer to the directive to be added
  788. *
  789. * Returns:
  790. *
  791. * If successful, the return value is zero. An error is indicated
  792. * by a negative return value.
  793. */
  794. int aclDirectiveAdd(ACL_t * acl, ACDirective_t * acd)
  795. {
  796. /* Add the directive to the end of the ACL's directive list */
  797. acd->acd_next = 0;
  798. if (acl->acl_dirl == 0) {
  799. /* First entry in empty list */
  800. acl->acl_dirf = acd;
  801. }
  802. else {
  803. /* Append to end of list */
  804. acl->acl_dirl->acd_next = acd;
  805. }
  806. acl->acl_dirl = acd;
  807. return 0;
  808. }
  809. /*
  810. * Description (aclDirectiveCreate)
  811. *
  812. * This function allocates and initializes a new ACDirective_t
  813. * structure, representing an ACL directive.
  814. *
  815. * Arguments:
  816. *
  817. * None.
  818. *
  819. * Returns:
  820. *
  821. * If successful, the return value is a pointer to a new ACDirective_t.
  822. * Otherwise the return value is null.
  823. */
  824. ACDirective_t * aclDirectiveCreate()
  825. {
  826. ACDirective_t * acd;
  827. acd = (ACDirective_t *) MALLOC(sizeof(ACDirective_t));
  828. if (acd != 0) {
  829. memset((void *)acd, 0, sizeof(ACDirective_t));
  830. }
  831. return acd;
  832. }
  833. /*
  834. * Description (aclDirectiveDestroy)
  835. *
  836. * This function destroys an ACL directive structure.
  837. *
  838. * Arguments:
  839. *
  840. * acd - pointer to ACL directive structure
  841. */
  842. void aclDirectiveDestroy(ACDirective_t * acd)
  843. {
  844. switch (acd->acd_action) {
  845. case ACD_ALLOW:
  846. case ACD_DENY:
  847. {
  848. ACClients_t * acp;
  849. ACClients_t * nacp;
  850. /* Free a list of ACClients_t structures */
  851. for (acp = acd->acd_cl; acp != 0; acp = nacp) {
  852. nacp = acp->cl_next;
  853. /* Free the HostSpec_t if it's there and unnamed */
  854. if ((acp->cl_host != 0) &&
  855. (acp->cl_host->hs_sym.sym_name == 0)) {
  856. aclHostSpecDestroy(acp->cl_host);
  857. }
  858. /* Free the UserSpec_t if it's there and unnamed */
  859. if ((acp->cl_user != 0) &&
  860. (acp->cl_user->us_sym.sym_name == 0)) {
  861. aclUserSpecDestroy(acp->cl_user);
  862. }
  863. }
  864. }
  865. break;
  866. case ACD_AUTH:
  867. {
  868. RealmSpec_t * rsp = acd->acd_auth.au_realm;
  869. /* Destroy the RealmSpec_t if it's unnamed */
  870. if ((rsp != 0) && (rsp->rs_sym.sym_name == 0)) {
  871. aclRealmSpecDestroy(rsp);
  872. }
  873. }
  874. break;
  875. }
  876. FREE(acd);
  877. }
  878. /*
  879. * Description (aclDNSSpecDestroy)
  880. *
  881. * This function destroys an entry in a DNS filter. It is intended
  882. * mainly to be used by aclHostSpecDestroy().
  883. *
  884. * Arguments:
  885. *
  886. * sym - pointer to Symbol_t for DNS filter entry
  887. * argp - unused (must be zero)
  888. *
  889. * Returns:
  890. *
  891. * The return value is SYMENUMREMOVE.
  892. */
  893. int aclDNSSpecDestroy(Symbol_t * sym, void * argp)
  894. {
  895. if (sym != 0) {
  896. /* Free the DNS specification string if any */
  897. if (sym->sym_name != 0) {
  898. FREE(sym->sym_name);
  899. }
  900. /* Free the Symbol_t structure */
  901. FREE(sym);
  902. }
  903. /* Indicate that the symbol table entry should be removed */
  904. return SYMENUMREMOVE;
  905. }
  906. /*
  907. * Description (aclHostSpecDestroy)
  908. *
  909. * This function destroys a HostSpec_t structure and its sub-structures.
  910. *
  911. * Arguments:
  912. *
  913. * hsp - pointer to HostSpec_t structure
  914. */
  915. void aclHostSpecDestroy(HostSpec_t * hsp)
  916. {
  917. if (hsp == 0) return;
  918. /* Free the IP filter if any */
  919. if (hsp->hs_host.inh_ipf.ipf_tree != 0) {
  920. IPNode_t * ipn; /* current node pointer */
  921. IPNode_t * parent; /* parent node pointer */
  922. int i;
  923. /* Traverse tree, freeing nodes */
  924. for (parent = hsp->hs_host.inh_ipf.ipf_tree; parent != NULL; ) {
  925. /* Look for a link to a child node */
  926. for (i = 0; i < IPN_NLINKS; ++i) {
  927. ipn = parent->ipn_links[i];
  928. if (ipn != NULL) break;
  929. }
  930. /* Any children for the parent node? */
  931. if (ipn == NULL) {
  932. /* Otherwise back up the tree */
  933. ipn = parent;
  934. parent = ipn->ipn_parent;
  935. /* Free the lower node */
  936. FREE(ipn);
  937. continue;
  938. }
  939. /*
  940. * Found a child node for the current parent.
  941. * NULL out the downward link and check it out.
  942. */
  943. parent->ipn_links[i] = NULL;
  944. /* Is it a leaf? */
  945. if (ipn->ipn_type == IPN_LEAF) {
  946. /* Yes, free it */
  947. FREE(ipn);
  948. continue;
  949. }
  950. /* No, step down the tree */
  951. parent = ipn;
  952. }
  953. }
  954. /* Free the DNS filter if any */
  955. if (hsp->hs_host.inh_dnf.dnf_hash != 0) {
  956. /* Destroy each entry in the symbol table */
  957. symTableEnumerate(hsp->hs_host.inh_dnf.dnf_hash, 0,
  958. aclDNSSpecDestroy);
  959. /* Destroy the symbol table itself */
  960. symTableDestroy(hsp->hs_host.inh_dnf.dnf_hash, 0);
  961. }
  962. /* Free the symbol name if any */
  963. if (hsp->hs_sym.sym_name != 0) {
  964. FREE(hsp->hs_sym.sym_name);
  965. }
  966. /* Free the HostSpec_t structure */
  967. FREE(hsp);
  968. }
  969. /*
  970. * Description (aclRealmSpecDestroy)
  971. *
  972. * This function destroys a RealmSpec_t structure.
  973. *
  974. * Arguments:
  975. *
  976. * rsp - pointer to RealmSpec_t structure
  977. */
  978. void aclRealmSpecDestroy(RealmSpec_t * rsp)
  979. {
  980. /* Close the realm authentication database if it appears open */
  981. if ((rsp->rs_realm.rlm_aif != 0) &&
  982. (rsp->rs_realm.rlm_authdb != 0)) {
  983. (*rsp->rs_realm.rlm_aif->aif_close)(rsp->rs_realm.rlm_authdb, 0);
  984. }
  985. /* Free the prompt string if any */
  986. if (rsp->rs_realm.rlm_prompt != 0) {
  987. FREE(rsp->rs_realm.rlm_prompt);
  988. }
  989. /* Free the database filename string if any */
  990. if (rsp->rs_realm.rlm_dbname != 0) {
  991. FREE(rsp->rs_realm.rlm_dbname);
  992. }
  993. /* Free the realm specification name if any */
  994. if (rsp->rs_sym.sym_name != 0) {
  995. FREE(rsp->rs_sym.sym_name);
  996. }
  997. /* Free the RealmSpec_t structure */
  998. FREE(rsp);
  999. }
  1000. /*
  1001. * Description (aclRightDef)
  1002. *
  1003. * This function find or creates an access right with a specified
  1004. * name in a given ACL context. If a new access right definition
  1005. * is created, it assigns a unique integer identifier to the the
  1006. * right, adds it to the ACL context symbol table and to the
  1007. * list of all access rights for the context. Note that access
  1008. * right names are case-insensitive.
  1009. *
  1010. * Arguments:
  1011. *
  1012. * errp - error frame list pointer (may be null)
  1013. * acc - pointer to an access control context
  1014. * rname - access right name (e.g. "GET")
  1015. * prd - pointer to returned RightDef_t pointer
  1016. * (may be null)
  1017. *
  1018. * Returns:
  1019. *
  1020. * The return value is zero if the access right definition already
  1021. * existed or one if it was created successfully. Otherwise it is
  1022. * a negative error code (ACLERRxxxx - see aclerror.h), and an error
  1023. * frame will be generated if an error list is provided.
  1024. */
  1025. int aclRightDef(NSErr_t * errp,
  1026. ACContext_t * acc, char * rname, RightDef_t **prd)
  1027. {
  1028. RightDef_t * rdp; /* pointer to right definition */
  1029. int eid; /* error id code */
  1030. int rv; /* result value */
  1031. static int last_rid = 0; /* last assigned right id */
  1032. /* See if there's already a symbol table entry for it */
  1033. rv = symTableFindSym(acc->acc_stp, rname, ACLSYMRIGHT, (void **)&rdp);
  1034. if (rv) {
  1035. /* No, create an entry */
  1036. /* Allocate a right definition structure and initialize it */
  1037. rdp = (RightDef_t *)MALLOC(sizeof(RightDef_t));
  1038. if (rdp == 0) goto err_nomem;
  1039. rdp->rd_sym.sym_name = STRDUP(rname);
  1040. rdp->rd_sym.sym_type = ACLSYMRIGHT;
  1041. rdp->rd_next = acc->acc_rights;
  1042. rdp->rd_id = ++last_rid;
  1043. /* Add the right name to the symbol table for the ACL context */
  1044. rv = symTableAddSym(acc->acc_stp, &rdp->rd_sym, (void *)rdp);
  1045. if (rv) goto err_stadd;
  1046. /* Add the right definition to the list for the ACL context */
  1047. acc->acc_rights = rdp;
  1048. /* Indicate a new right definition was created */
  1049. rv = 1;
  1050. }
  1051. /* Return a pointer to the RightDef_t structure if indicated */
  1052. if (prd != 0) *prd = rdp;
  1053. return rv;
  1054. err_nomem:
  1055. eid = ACLERR3600;
  1056. rv = ACLERRNOMEM;
  1057. nserrGenerate(errp, rv, eid, ACL_Program, 0);
  1058. goto punt;
  1059. err_stadd:
  1060. FREE(rdp->rd_sym.sym_name);
  1061. FREE(rdp);
  1062. eid = ACLERR3620;
  1063. rv = ACLERRDUPSYM;
  1064. nserrGenerate(errp, rv, eid, ACL_Program, 1, rname);
  1065. punt:
  1066. return rv;
  1067. }
  1068. /*
  1069. * Description (aclRightSpecDestroy)
  1070. *
  1071. * This function destroys a RightSpec_t structure.
  1072. *
  1073. * Arguments:
  1074. *
  1075. * rsp - pointer to RightSpec_t structure
  1076. */
  1077. void aclRightSpecDestroy(RightSpec_t * rsp)
  1078. {
  1079. if (rsp != 0) {
  1080. UILFREE(&rsp->rs_list);
  1081. if (rsp->rs_sym.sym_name != 0) {
  1082. FREE(rsp->rs_sym.sym_name);
  1083. }
  1084. FREE(rsp);
  1085. }
  1086. }
  1087. /*
  1088. * Description (aclUserSpecCreate)
  1089. *
  1090. * This function allocates and initializes a new UserSpec_t
  1091. * structure, representing a list of users and groups.
  1092. *
  1093. * Arguments:
  1094. *
  1095. * None.
  1096. *
  1097. * Returns:
  1098. *
  1099. * If successful, the return value is a pointer to a new UserSpec_t.
  1100. * Otherwise the return value is null.
  1101. */
  1102. UserSpec_t * aclUserSpecCreate()
  1103. {
  1104. UserSpec_t * usp;
  1105. usp = (UserSpec_t *) MALLOC(sizeof(UserSpec_t));
  1106. if (usp != 0) {
  1107. memset((void *)usp, 0, sizeof(UserSpec_t));
  1108. usp->us_sym.sym_type = ACLSYMUSER;
  1109. }
  1110. return usp;
  1111. }
  1112. /*
  1113. * Description (aclUserSpecDestroy)
  1114. *
  1115. * This function destroys a UserSpec_t structure.
  1116. *
  1117. * Arguments:
  1118. *
  1119. * usp - pointer to UserSpec_t structure
  1120. */
  1121. void aclUserSpecDestroy(UserSpec_t * usp)
  1122. {
  1123. if (usp != 0) {
  1124. UILFREE(&usp->us_user.uu_user);
  1125. UILFREE(&usp->us_user.uu_group);
  1126. if (usp->us_sym.sym_name != 0) {
  1127. FREE(usp->us_sym.sym_name);
  1128. }
  1129. FREE(usp);
  1130. }
  1131. }