diff options
Diffstat (limited to 'lib/libaccess/aclbuild.cpp')
-rw-r--r-- | lib/libaccess/aclbuild.cpp | 1360 |
1 files changed, 0 insertions, 1360 deletions
diff --git a/lib/libaccess/aclbuild.cpp b/lib/libaccess/aclbuild.cpp deleted file mode 100644 index d7ff6283..00000000 --- a/lib/libaccess/aclbuild.cpp +++ /dev/null @@ -1,1360 +0,0 @@ -/** BEGIN COPYRIGHT BLOCK - * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. - * All rights reserved. - * END COPYRIGHT BLOCK **/ - -/* - * Description (aclbuild.c) - * - * This module provides functions for building Access Control List - * (ACL) structures in memory. - * - */ - -#include <assert.h> -#include "base/systems.h" -#include "netsite.h" -#include "libaccess/nsauth.h" -#include "libaccess/nsuser.h" -#include "libaccess/nsgroup.h" -#include "libaccess/nsadb.h" -#include "libaccess/aclerror.h" -#include "libaccess/aclstruct.h" -#include "libaccess/aclbuild.h" -#include "libaccess/aclparse.h" -#include "libaccess/acleval.h" -#include "libaccess/usi.h" - -char * ACL_Program = "NSACL"; /* ACL facility name */ - -/* - * Description (accCreate) - * - * This function creates a new access control context, which - * provides context information for a set of ACL definitions. - * The caller also provides a handle for a symbol table to be - * used to store definitions of ACL and rights names. - * - * Arguments: - * - * errp - error frame list pointer (may be null) - * stp - symbol table handle (may be null) - * pacc - pointer to returned context handle - * - * Returns: - * - * If the context is created successfully, the return value is zero. - * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h), - * and an error frame will be generated if an error list is provided. - */ - -int accCreate(NSErr_t * errp, void * stp, ACContext_t **pacc) -{ - ACContext_t * acc; /* pointer to new context */ - int rv; /* result value */ - int eid; /* error id */ - - *pacc = 0; - - /* Do we need to create a symbol table? */ - if (stp == 0) { - - /* Yes, create a symbol table for ACL, rights, etc. names */ - rv = symTableNew(&stp); - if (rv < 0) goto err_nomem1; - } - - /* Allocate the context structure */ - acc = (ACContext_t *)MALLOC(sizeof(ACContext_t)); - if (acc == 0) goto err_nomem2; - - /* Initialize it */ - acc->acc_stp = stp; - acc->acc_acls = 0; - acc->acc_rights = 0; - acc->acc_refcnt = 0; - - *pacc = acc; - return 0; - - err_nomem1: - rv = ACLERRNOMEM; - eid = ACLERR3000; - goto err_ret; - - err_nomem2: - rv = ACLERRNOMEM; - eid = ACLERR3020; - - err_ret: - nserrGenerate(errp, rv, eid, ACL_Program, 0); - return rv; -} - -/* - * Description (accDestroy) - * - * This function destroys a set of ACL data structures referenced - * by a specified ACContext_t structure, including the ACContext_t - * itself. - * - * Arguments: - * - * acc - pointer to ACContext_t structure - * flags - bit flags (unused - must be zero) - */ - -void accDestroy(ACContext_t * acc, int flags) -{ - ACL_t * acl; - - if (acc != 0) { - - /* - * First destroy all ACLs and any unnamed structures they reference. - * Note that aclDestroy() modifies the acc_acls list. - */ - while ((acl = acc->acc_acls) != 0) { - - aclDelete(acl); - } - - /* If there's a symbol table, destroy everything it references */ - if (acc->acc_stp != 0) { - symTableEnumerate(acc->acc_stp, 0, accDestroySym); - - /* Destroy the symbol table itself */ - symTableDestroy(acc->acc_stp, 0); - } - - /* Free the ACContext_t structure */ - FREE(acc); - } -} - -/* - * Description (accDestroySym) - * - * This function is called to destroy the data structure associated - * with a specified Symbol_t symbol table entry. It examines the - * type of the symbol and calls the appropriate destructor. - * - * Arguments: - * - * sym - pointer to symbol table entry - * argp - unused - must be zero - * - * Returns: - * - * The return value is SYMENUMREMOVE. - */ - -int accDestroySym(Symbol_t * sym, void * argp) -{ - switch (sym->sym_type) { - case ACLSYMACL: /* ACL */ - aclDestroy((ACL_t *)sym); - break; - - case ACLSYMRIGHT: /* access right */ - { - RightDef_t * rdp = (RightDef_t *)sym; - - if (rdp->rd_sym.sym_name != 0) { - FREE(rdp->rd_sym.sym_name); - } - FREE(rdp); - } - break; - - case ACLSYMRDEF: /* access rights list */ - aclRightSpecDestroy((RightSpec_t *)sym); - break; - - case ACLSYMREALM: /* realm name */ - aclRealmSpecDestroy((RealmSpec_t *)sym); - break; - - case ACLSYMHOST: /* host specifications */ - aclHostSpecDestroy((HostSpec_t *)sym); - break; - - case ACLSYMUSER: /* user/group list */ - aclUserSpecDestroy((UserSpec_t *)sym); - break; - } - - return SYMENUMREMOVE; -} - -/* - * Description (accReadFile) - * - * This function reads a specfied file containing ACL definitions - * and creates data structures in memory to represent the ACLs. - * The caller may provide a pointer to an existing ACContext_t - * structure which will serve as the root of the ACL structures, - * or else a new one will be created. - * - * Arguments: - * - * errp - error frame list pointer (may be null) - * aclfile - pointer to the ACL filename string - * pacc - value/result ACContext_t - * - * Returns: - * - * If the ACL file is read successfully, the return value is zero. - * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h), - * and an error frame will be generated if an error list is provided. - */ - -int accReadFile(NSErr_t * errp, char * aclfile, ACContext_t **pacc) -{ - ACContext_t * acc = *pacc; /* pointer to ACL root structure */ - ACLFile_t * acf = 0; /* pointer to ACL file handle */ - void * stp = 0; /* ACL symbol table handle */ - int rv; /* result value */ - int eid; /* error id value */ - - /* Initialize the ACL parser */ - rv = aclParseInit(); - if (rv < 0) goto err_init; - - /* Do we need to create a new ACContext_t structure? */ - if (acc == 0) { - - /* Yes, create a symbol table for ACL, rights, etc. names */ - rv = symTableNew(&stp); - if (rv < 0) goto err_crsym; - - /* Create a root structure for the ACLs, including the symbol table */ - rv = accCreate(errp, stp, &acc); - if (rv < 0) goto err_ret2; - } - - /* Open the ACL definition file */ - rv = aclFileOpen(errp, aclfile, 0, &acf); - if (rv < 0) goto err_ret3; - - /* Parse the ACL definitions, building ACL structures in memory */ - rv = aclACLParse(errp, acf, acc, 0); - if (rv < 0) goto err_ret4; - - aclFileClose(acf, 0); - - if (pacc) *pacc = acc; - - return rv; - - err_init: - eid = ACLERR3100; - goto err_ret; - - err_crsym: - eid = ACLERR3120; - rv = ACLERRNOMEM; - goto err_ret; - - err_ret4: - aclFileClose(acf, 0); - err_ret3: - /* Destroy the ACContext_t if we just created it */ - if (acc != *pacc) { - accDestroy(acc, 0); - } - goto err_ret; - - err_ret2: - symTableDestroy(stp, 0); - - err_ret: - return rv; -} - -/* - * Description (aclAuthDNSAdd) - * - * This function adds a DNS name specification to the DNS filter - * associated with a given host list. The DNS name specification is - * either a fully-qualified domain name or a domain name suffix, - * indicated by a leading ".", e.g. (".mcom.com"). The name - * components included in a suffix must be complete. For example, - * ".scape.com" will not match names ending in ".netscape.com". - * - * Arguments: - * - * hspp - pointer to host list pointer - * dnsspec - DNS name or suffix string pointer - * fqdn - non-zero if dnsspec is fully qualified - * - * Returns: - * - * If successful, the return code is zero. - * An error is indicated by a negative return code (ACLERRxxxx - * - see aclerror.h). - */ - -int aclAuthDNSAdd(HostSpec_t **hspp, char * dnsspec, int fqdn) -{ - HostSpec_t * hsp; /* host list pointer */ - void * table; /* access control hash table pointer */ - Symbol_t * sym; /* hash table entry pointer */ - int rv; /* result value */ - - fqdn = (fqdn) ? 1 : 0; - - /* Create the HostSpec_t if it doesn't exist */ - hsp = *hspp; - if (hsp == 0) { - - hsp = (HostSpec_t *)MALLOC(sizeof(HostSpec_t)); - if (hsp == 0) goto err_nomem; - memset((void *)hsp, 0, sizeof(HostSpec_t)); - hsp->hs_sym.sym_type = ACLSYMHOST; - } - - /* Get pointer to hash table used for DNS filter */ - table = hsp->hs_host.inh_dnf.dnf_hash; - if (table == 0) { - - /* None there yet, so create one */ - rv = symTableNew(&table); - if (rv < 0) goto punt; - hsp->hs_host.inh_dnf.dnf_hash = table; - } - - /* See if the DNS spec is already in the table */ - rv = symTableFindSym(table, dnsspec, fqdn, (void **)&sym); - if (rv < 0) { - if (rv != SYMERRNOSYM) goto punt; - - /* It's not there, so add it */ - sym = (Symbol_t *)MALLOC(sizeof(Symbol_t)); - sym->sym_name = STRDUP(dnsspec); - sym->sym_type = fqdn; - - rv = symTableAddSym(table, sym, (void *)sym); - if (rv < 0) goto err_nomem; - } - - *hspp = hsp; - - punt: - return rv; - - err_nomem: - rv = ACLERRNOMEM; - goto punt; -} - -/* - * Description (aclAuthIPAdd) - * - * This function adds an IP address specification to the IP filter - * associated with a given host list. The IP address specification - * consists of an IP host or network address and an IP netmask. - * For host addresses the netmask value is 255.255.255.255. - * - * Arguments: - * - * hspp - pointer to host list pointer - * ipaddr - IP host or network address - * netmask - IP netmask value - * - * Returns: - * - * If successful, the return code is zero. - * An error is indicated by a negative return code (ACLERRxxxx - * - see aclerror.h). - */ - -int aclAuthIPAdd(HostSpec_t **hspp, IPAddr_t ipaddr, IPAddr_t netmask) -{ - HostSpec_t * hsp; /* host list pointer */ - IPFilter_t * ipf; /* IP filter pointer */ - IPNode_t * ipn; /* current node pointer */ - IPNode_t * lastipn; /* last (lower) node pointer */ - IPLeaf_t * leaf; /* leaf node pointer */ - IPAddr_t bitmask; /* bit mask for current node */ - int lastbit; /* number of last bit set in netmask */ - int i; /* loop index */ - - /* Create the HostSpec_t if it doesn't exist */ - hsp = *hspp; - if (hsp == 0) { - - hsp = (HostSpec_t *)MALLOC(sizeof(HostSpec_t)); - if (hsp == 0) goto err_nomem; - memset((void *)hsp, 0, sizeof(HostSpec_t)); - hsp->hs_sym.sym_type = ACLSYMHOST; - } - - ipf = &hsp->hs_host.inh_ipf; - - /* If the filter doesn't have a root node yet, create it */ - if (ipf->ipf_tree == 0) { - - /* Allocate node */ - ipn = (IPNode_t *)MALLOC(sizeof(IPNode_t)); - if (ipn == 0) goto err_nomem; - - /* Initialize it to test bit 31, but without any descendants */ - ipn->ipn_type = IPN_NODE; - ipn->ipn_bit = 31; - ipn->ipn_parent = NULL; - ipn->ipn_clear = NULL; - ipn->ipn_set = NULL; - ipn->ipn_masked = NULL; - - /* Set it as the root node in the radix tree */ - ipf->ipf_tree = ipn; - } - - /* First we search the tree to see where this IP specification fits */ - - lastipn = NULL; - - for (ipn = ipf->ipf_tree; (ipn != NULL) && (ipn->ipn_type == IPN_NODE); ) { - - /* Get a mask for the bit this node tests */ - bitmask = (IPAddr_t) 1<<ipn->ipn_bit; - - /* Save pointer to last internal node */ - lastipn = ipn; - - /* Is this a bit we care about? */ - if (bitmask & netmask) { - - /* Yes, get address of set or clear descendant pointer */ - ipn = (bitmask & ipaddr) ? ipn->ipn_set : ipn->ipn_clear; - } - else { - /* No, get the address of the masked descendant pointer */ - ipn = ipn->ipn_masked; - } - } - - /* Did we end up at a leaf node? */ - if (ipn == NULL) { - - /* - * No, well, we need to find a leaf node if possible. The - * reason is that we need an IP address and netmask to compare - * to the IP address and netmask we're inserting. We know that - * they're the same up to the bit tested by the lastipn node, - * but we need to know the *highest* order bit that's different. - * Any leaf node below lastipn will do. - */ - - leaf = NULL; - ipn = lastipn; - - while (ipn != NULL) { - - /* Look for any non-null child link of the current node */ - for (i = 0; i < IPN_NLINKS; ++i) { - if (ipn->ipn_links[i]) break; - } - - /* - * Fail search for leaf if no non-null child link found. - * This should only happen on the root node of the tree - * when the tree is empty. - */ - if (i >= IPN_NLINKS) { - assert(ipn == ipf->ipf_tree); - break; - } - - /* Step to the child node */ - ipn = ipn->ipn_links[i]; - - /* Is it a leaf? */ - if (ipn->ipn_type == IPN_LEAF) { - - /* Yes, search is over */ - leaf = (IPLeaf_t *)ipn; - ipn = NULL; - break; - } - } - } - else { - - /* Yes, loop terminated on a leaf node */ - assert(ipn->ipn_type == IPN_LEAF); - leaf = (IPLeaf_t *)ipn; - } - - /* Got a leaf yet? */ - if (leaf != NULL) { - - /* Combine the IP address and netmask differences */ - bitmask = (leaf->ipl_ipaddr ^ ipaddr) | (leaf->ipl_netmask ^ netmask); - - /* Are both the IP address and the netmask the same? */ - if (bitmask == 0) { - - /* Yes, duplicate entry */ - return 0; - } - - /* Find the bit number of the first different bit */ - for (lastbit = 31; - (bitmask & 0x80000000) == 0; --lastbit, bitmask <<= 1) ; - - /* Generate a bit mask with just that bit */ - bitmask = (IPAddr_t) (1 << lastbit); - - /* - * Go up the tree from lastipn, looking for an internal node - * that tests lastbit. Stop if we get to a node that tests - * a higher bit number first. - */ - for (ipn = lastipn, lastipn = (IPNode_t *)leaf; - ipn != NULL; ipn = ipn->ipn_parent) { - - if (ipn->ipn_bit >= lastbit) { - if (ipn->ipn_bit == lastbit) { - /* Need to add a leaf off ipn node */ - lastipn = NULL; - } - break; - } - lastipn = ipn; - } - - assert(ipn != NULL); - } - else { - - /* Just hang a leaf off the lastipn node if no leaf */ - ipn = lastipn; - lastipn = NULL; - lastbit = ipn->ipn_bit; - } - - /* - * If lastipn is not NULL at this point, the new leaf will hang - * off an internal node inserted between the upper node, referenced - * by ipn, and the lower node, referenced by lastipn. The lower - * node may be an internal node or a leaf. - */ - if (lastipn != NULL) { - IPNode_t * parent = ipn; /* parent of the new node */ - - assert((lastipn->ipn_type == IPN_LEAF) || - (ipn == lastipn->ipn_parent)); - - /* Allocate space for the internal node */ - ipn = (IPNode_t *)MALLOC(sizeof(IPNode_t)); - if (ipn == NULL) goto err_nomem; - - ipn->ipn_type = IPN_NODE; - ipn->ipn_bit = lastbit; - ipn->ipn_parent = parent; - ipn->ipn_clear = NULL; - ipn->ipn_set = NULL; - ipn->ipn_masked = NULL; - - bitmask = (IPAddr_t) (1 << lastbit); - - /* - * The values in the leaf we found above determine which - * descendant link of the new internal node will reference - * the subtree that we just ascended. - */ - if (leaf->ipl_netmask & bitmask) { - if (leaf->ipl_ipaddr & bitmask) { - ipn->ipn_set = lastipn; - } - else { - ipn->ipn_clear = lastipn; - } - } - else { - ipn->ipn_masked = lastipn; - } - - /* Allocate space for the new leaf */ - leaf = (IPLeaf_t *)MALLOC(sizeof(IPLeaf_t)); - if (leaf == NULL) { - FREE((void *)ipn); - goto err_nomem; - } - - /* Insert internal node in tree */ - - /* First the downward link from the parent to the new node */ - for (i = 0; i < IPN_NLINKS; ++i) { - if (parent->ipn_links[i] == lastipn) { - parent->ipn_links[i] = ipn; - break; - } - } - - /* Then the upward link from the child (if it's not a leaf) */ - if (lastipn->ipn_type == IPN_NODE) { - lastipn->ipn_parent = ipn; - } - } - else { - /* Allocate space for a leaf node only */ - leaf = (IPLeaf_t *)MALLOC(sizeof(IPLeaf_t)); - if (leaf == NULL) goto err_nomem; - } - - /* Initialize the new leaf */ - leaf->ipl_type = IPN_LEAF; - leaf->ipl_ipaddr = ipaddr; - leaf->ipl_netmask = netmask; - - /* - * Select the appropriate descendant link of the internal node - * and point it at the new leaf. - */ - bitmask = (IPAddr_t) (1 << ipn->ipn_bit); - if (bitmask & netmask) { - if (bitmask & ipaddr) { - assert(ipn->ipn_set == NULL); - ipn->ipn_set = (IPNode_t *)leaf; - } - else { - assert(ipn->ipn_clear == NULL); - ipn->ipn_clear = (IPNode_t *)leaf; - } - } - else { - assert(ipn->ipn_masked == NULL); - ipn->ipn_masked = (IPNode_t *)leaf; - } - - *hspp = hsp; - - /* Successful completion */ - return 0; - - err_nomem: - return ACLERRNOMEM; -} - -/* - * Description (aclAuthNameAdd) - * - * This function adds a user or group to a given user list, - * in the context of a specified ACL that is being created. The - * name of the user or group is provided by the caller, and is - * looked up in the authentication database associated with the - * specified user list. The return value indicates whether the name - * matched a user or group name, and whether the corresponding user - * or group id was already present in the given user list. - * - * Arguments: - * - * errp - error frame list pointer (may be null) - * usp - pointer to user list specification - * rlm - pointer to current authentication realm - * name - pointer to user or group name string - * - * Returns: - * - * The return value is zero if the name is not found in the - * authentication database. If the name is found, the return value - * is a positive value containing bit flags: - * - * AIF_GROUP - name matches a group name - * AIF_USER - name matches a user name - * AIF_DUP - name was already represented in the - * specified user list - * - * An error is indicated by a negative return code (ACLERRxxxx - * - see aclerror.h), and an error frame will be generated if - * an error list is provided. - */ - -int aclAuthNameAdd(NSErr_t * errp, UserSpec_t * usp, - Realm_t * rlm, char * name) -{ - void * guoptr; /* group or user object pointer */ - int irv; /* insert result value */ - int eid; /* error id */ - int rv; /* result value */ - - /* There must be a realm specified in order to handle users */ - if (rlm == 0) goto err_norealm; - - /* Open the authentication database if it's not already */ - if (rlm->rlm_authdb == 0) { - - if (rlm->rlm_aif == 0) { - rlm->rlm_aif = &NSADB_AuthIF; - } - - rv = (*rlm->rlm_aif->aif_open)(errp, - rlm->rlm_dbname, 0, &rlm->rlm_authdb); - if (rv < 0) goto err_open; - } - - /* Look up the name in the authentication DB */ - rv = (*rlm->rlm_aif->aif_findname)(errp, rlm->rlm_authdb, name, - (AIF_USER|AIF_GROUP), (void **)&guoptr); - if (rv <= 0) { - if (rv < 0) goto err_adb; - - /* The name was not found in the database */ - return 0; - } - - /* The name was found. Was it a user name? */ - if (rv == AIF_USER) { - - /* Yes, add the user id to the user list */ - irv = usiInsert(&usp->us_user.uu_user, ((UserObj_t *)guoptr)->uo_uid); - rv = ANA_USER; - } - else { - - /* No, must be a group name. Add group id to an_groups list. */ - irv = usiInsert(&usp->us_user.uu_group, - ((GroupObj_t *)guoptr)->go_gid); - rv = ANA_GROUP; - } - - /* Examine the result of the insert operation */ - if (irv <= 0) { - if (irv < 0) goto err_ins; - - /* Id was already in the list */ - rv |= ANA_DUP; - } - - punt: - return rv; - - err_norealm: - eid = ACLERR3400; - rv = ACLERRNORLM; - nserrGenerate(errp, rv, eid, ACL_Program, 1, name); - goto punt; - - err_open: - eid = ACLERR3420; - rv = ACLERROPEN; - nserrGenerate(errp, rv, eid, ACL_Program, - 2, rlm->rlm_dbname, system_errmsg()); - goto punt; - - err_adb: - /* Error accessing authentication database. */ - eid = ACLERR3440; - rv = ACLERRADB; - nserrGenerate(errp, rv, eid, ACL_Program, 2, rlm->rlm_dbname, name); - goto punt; - - err_ins: - /* Error on insert operation. Must be lack of memory. */ - eid = ACLERR3460; - rv = ACLERRNOMEM; - nserrGenerate(errp, rv, eid, ACL_Program, 0); - goto punt; -} - -/* - * Description (aclClientsDirCreate) - * - * This function allocates and initializes a new ACClients_t - * ACL directive. - * - * Arguments: - * - * None. - * - * Returns: - * - * If successful, a pointer to the new ACClients_t is returned. - * A shortage of dynamic memory is indicated by a null return value. - */ - -ACClients_t * aclClientsDirCreate() -{ - ACClients_t * acd; /* pointer to new ACClients_t */ - - acd = (ACClients_t *)MALLOC(sizeof(ACClients_t)); - if (acd != 0) { - memset((void *)acd, 0, sizeof(ACClients_t)); - } - - return acd; -} - -/* - * Description (aclCreate) - * - * This function creates a new ACL root structure. The caller - * specifies the name to be associated with the ACL. The ACL handle - * returned by this function is passed to other functions in this - * module when adding information to the ACL. - * - * Arguments: - * - * errp - error frame list pointer (may be null) - * acc - pointer to an access control context - * aclname - pointer to ACL name string - * pacl - pointer to returned ACL handle - * - * Returns: - * - * The return value is zero if the ACL is created successfully. - * Otherwise it is a negative error code (ACLERRxxxx - see aclerror.h), - * and an error frame will be generated if an error list is provided. - */ - -int aclCreate(NSErr_t * errp, ACContext_t * acc, char * aclname, ACL_t **pacl) -{ - ACL_t * acl; /* pointer to created ACL */ - int rv; /* result value */ - int eid; /* error id */ - - *pacl = 0; - - /* Allocate the ACL_t structure */ - acl = (ACL_t *) MALLOC(sizeof(ACL_t)); - if (acl == 0) goto err_nomem; - - /* Initialize the structure */ - memset((void *)acl, 0, sizeof(ACL_t)); - acl->acl_sym.sym_name = STRDUP(aclname); - acl->acl_sym.sym_type = ACLSYMACL; - acl->acl_acc = acc; - acl->acl_refcnt = 1; - - /* Add it to the symbol table for the specified context */ - rv = symTableAddSym(acc->acc_stp, &acl->acl_sym, (void *)acl); - if (rv < 0) goto err_addsym; - - /* Add it to the list of ACLs for the specified context */ - acl->acl_next = acc->acc_acls; - acc->acc_acls = acl; - acc->acc_refcnt += 1; - - *pacl = acl; - return 0; - - err_nomem: - rv = ACLERRNOMEM; - eid = ACLERR3200; - nserrGenerate(errp, rv, eid, ACL_Program, 0); - goto done; - - err_addsym: - FREE(acl); - rv = ACLERRDUPSYM; - eid = ACLERR3220; - nserrGenerate(errp, rv, eid, ACL_Program, 1, aclname); - - done: - return rv; -} - -/* - * Description (aclDestroy) - * - * This function destroys an ACL structure and its sub-structures. - * It does not free the ACContext_t referenced by the ACL. - * - * Arguments: - * - * acl - pointer to ACL_t structure - */ - -void aclDestroy(ACL_t * acl) -{ - ACL_t **pacl; /* ACL list link pointer */ - ACDirective_t * acd; /* ACL directive pointer */ - ACDirective_t * nacd; /* next ACL directive pointer */ - - /* Is there an ACContext_t structure? */ - if (acl->acl_acc != 0) { - - /* Remove this ACL from the list in the ACContext_t structure */ - for (pacl = &acl->acl_acc->acc_acls; - *pacl != 0; pacl = &(*pacl)->acl_next) { - - if (*pacl == acl) { - *pacl = acl->acl_next; - acl->acl_acc->acc_refcnt -= 1; - break; - } - } - } - - /* Destroy each ACL directive */ - for (acd = acl->acl_dirf; acd != 0; acd = nacd) { - nacd = acd->acd_next; - aclDirectiveDestroy(acd); - } - - /* Free the ACL rights list if it is unnamed */ - if ((acl->acl_rights != 0) && (acl->acl_rights->rs_sym.sym_name == 0)) { - aclRightSpecDestroy(acl->acl_rights); - } - - /* Free the ACL name string, if any */ - if (acl->acl_sym.sym_name != 0) { - FREE(acl->acl_sym.sym_name); - } - - /* Free the ACL itself */ - FREE(acl); -} - -/* - * Description (aclDelete) - * - * This function removes a specified ACL from the symbol table - * associated with its ACL context, and then destroys the ACL - * structure and any unnamed objects it references (other than - * the ACL context). - * - * Arguments: - * - * acl - pointer to the ACL - */ - -void aclDelete(ACL_t * acl) -{ - ACContext_t * acc = acl->acl_acc; - - if ((acc != 0) && (acl->acl_sym.sym_name != 0)) { - symTableRemoveSym(acc->acc_stp, &acl->acl_sym); - } - - aclDestroy(acl); -} - -/* - * Description (aclDirectiveAdd) - * - * This function adds a given directive to a specified ACL. - * - * Arguments: - * - * acl - pointer to the ACL - * acd - pointer to the directive to be added - * - * Returns: - * - * If successful, the return value is zero. An error is indicated - * by a negative return value. - */ - -int aclDirectiveAdd(ACL_t * acl, ACDirective_t * acd) -{ - /* Add the directive to the end of the ACL's directive list */ - acd->acd_next = 0; - - if (acl->acl_dirl == 0) { - /* First entry in empty list */ - acl->acl_dirf = acd; - } - else { - /* Append to end of list */ - acl->acl_dirl->acd_next = acd; - } - - acl->acl_dirl = acd; - - return 0; -} - -/* - * Description (aclDirectiveCreate) - * - * This function allocates and initializes a new ACDirective_t - * structure, representing an ACL directive. - * - * Arguments: - * - * None. - * - * Returns: - * - * If successful, the return value is a pointer to a new ACDirective_t. - * Otherwise the return value is null. - */ - -ACDirective_t * aclDirectiveCreate() -{ - ACDirective_t * acd; - - acd = (ACDirective_t *) MALLOC(sizeof(ACDirective_t)); - if (acd != 0) { - memset((void *)acd, 0, sizeof(ACDirective_t)); - } - - return acd; -} - -/* - * Description (aclDirectiveDestroy) - * - * This function destroys an ACL directive structure. - * - * Arguments: - * - * acd - pointer to ACL directive structure - */ - -void aclDirectiveDestroy(ACDirective_t * acd) -{ - switch (acd->acd_action) { - case ACD_ALLOW: - case ACD_DENY: - { - ACClients_t * acp; - ACClients_t * nacp; - - /* Free a list of ACClients_t structures */ - for (acp = acd->acd_cl; acp != 0; acp = nacp) { - nacp = acp->cl_next; - - /* Free the HostSpec_t if it's there and unnamed */ - if ((acp->cl_host != 0) && - (acp->cl_host->hs_sym.sym_name == 0)) { - aclHostSpecDestroy(acp->cl_host); - } - - /* Free the UserSpec_t if it's there and unnamed */ - if ((acp->cl_user != 0) && - (acp->cl_user->us_sym.sym_name == 0)) { - aclUserSpecDestroy(acp->cl_user); - } - } - } - break; - - case ACD_AUTH: - { - RealmSpec_t * rsp = acd->acd_auth.au_realm; - - /* Destroy the RealmSpec_t if it's unnamed */ - if ((rsp != 0) && (rsp->rs_sym.sym_name == 0)) { - aclRealmSpecDestroy(rsp); - } - } - break; - } - - FREE(acd); -} - -/* - * Description (aclDNSSpecDestroy) - * - * This function destroys an entry in a DNS filter. It is intended - * mainly to be used by aclHostSpecDestroy(). - * - * Arguments: - * - * sym - pointer to Symbol_t for DNS filter entry - * argp - unused (must be zero) - * - * Returns: - * - * The return value is SYMENUMREMOVE. - */ - -int aclDNSSpecDestroy(Symbol_t * sym, void * argp) -{ - if (sym != 0) { - - /* Free the DNS specification string if any */ - if (sym->sym_name != 0) { - FREE(sym->sym_name); - } - - /* Free the Symbol_t structure */ - FREE(sym); - } - - /* Indicate that the symbol table entry should be removed */ - return SYMENUMREMOVE; -} - -/* - * Description (aclHostSpecDestroy) - * - * This function destroys a HostSpec_t structure and its sub-structures. - * - * Arguments: - * - * hsp - pointer to HostSpec_t structure - */ - -void aclHostSpecDestroy(HostSpec_t * hsp) -{ - if (hsp == 0) return; - - /* Free the IP filter if any */ - if (hsp->hs_host.inh_ipf.ipf_tree != 0) { - IPNode_t * ipn; /* current node pointer */ - IPNode_t * parent; /* parent node pointer */ - int i; - - /* Traverse tree, freeing nodes */ - for (parent = hsp->hs_host.inh_ipf.ipf_tree; parent != NULL; ) { - - /* Look for a link to a child node */ - for (i = 0; i < IPN_NLINKS; ++i) { - ipn = parent->ipn_links[i]; - if (ipn != NULL) break; - } - - /* Any children for the parent node? */ - if (ipn == NULL) { - - /* Otherwise back up the tree */ - ipn = parent; - parent = ipn->ipn_parent; - - /* Free the lower node */ - FREE(ipn); - continue; - } - - /* - * Found a child node for the current parent. - * NULL out the downward link and check it out. - */ - parent->ipn_links[i] = NULL; - - /* Is it a leaf? */ - if (ipn->ipn_type == IPN_LEAF) { - /* Yes, free it */ - FREE(ipn); - continue; - } - - /* No, step down the tree */ - parent = ipn; - } - } - - /* Free the DNS filter if any */ - if (hsp->hs_host.inh_dnf.dnf_hash != 0) { - - /* Destroy each entry in the symbol table */ - symTableEnumerate(hsp->hs_host.inh_dnf.dnf_hash, 0, - aclDNSSpecDestroy); - - /* Destroy the symbol table itself */ - symTableDestroy(hsp->hs_host.inh_dnf.dnf_hash, 0); - } - - /* Free the symbol name if any */ - if (hsp->hs_sym.sym_name != 0) { - FREE(hsp->hs_sym.sym_name); - } - - /* Free the HostSpec_t structure */ - FREE(hsp); -} - -/* - * Description (aclRealmSpecDestroy) - * - * This function destroys a RealmSpec_t structure. - * - * Arguments: - * - * rsp - pointer to RealmSpec_t structure - */ - -void aclRealmSpecDestroy(RealmSpec_t * rsp) -{ - /* Close the realm authentication database if it appears open */ - if ((rsp->rs_realm.rlm_aif != 0) && - (rsp->rs_realm.rlm_authdb != 0)) { - (*rsp->rs_realm.rlm_aif->aif_close)(rsp->rs_realm.rlm_authdb, 0); - } - - /* Free the prompt string if any */ - if (rsp->rs_realm.rlm_prompt != 0) { - FREE(rsp->rs_realm.rlm_prompt); - } - - /* Free the database filename string if any */ - if (rsp->rs_realm.rlm_dbname != 0) { - FREE(rsp->rs_realm.rlm_dbname); - } - - /* Free the realm specification name if any */ - if (rsp->rs_sym.sym_name != 0) { - FREE(rsp->rs_sym.sym_name); - } - - /* Free the RealmSpec_t structure */ - FREE(rsp); -} - -/* - * Description (aclRightDef) - * - * This function find or creates an access right with a specified - * name in a given ACL context. If a new access right definition - * is created, it assigns a unique integer identifier to the the - * right, adds it to the ACL context symbol table and to the - * list of all access rights for the context. Note that access - * right names are case-insensitive. - * - * Arguments: - * - * errp - error frame list pointer (may be null) - * acc - pointer to an access control context - * rname - access right name (e.g. "GET") - * prd - pointer to returned RightDef_t pointer - * (may be null) - * - * Returns: - * - * The return value is zero if the access right definition already - * existed or one if it was created successfully. Otherwise it is - * a negative error code (ACLERRxxxx - see aclerror.h), and an error - * frame will be generated if an error list is provided. - */ - -int aclRightDef(NSErr_t * errp, - ACContext_t * acc, char * rname, RightDef_t **prd) -{ - RightDef_t * rdp; /* pointer to right definition */ - int eid; /* error id code */ - int rv; /* result value */ - static int last_rid = 0; /* last assigned right id */ - - /* See if there's already a symbol table entry for it */ - rv = symTableFindSym(acc->acc_stp, rname, ACLSYMRIGHT, (void **)&rdp); - if (rv) { - - /* No, create an entry */ - - /* Allocate a right definition structure and initialize it */ - rdp = (RightDef_t *)MALLOC(sizeof(RightDef_t)); - if (rdp == 0) goto err_nomem; - - rdp->rd_sym.sym_name = STRDUP(rname); - rdp->rd_sym.sym_type = ACLSYMRIGHT; - rdp->rd_next = acc->acc_rights; - rdp->rd_id = ++last_rid; - - /* Add the right name to the symbol table for the ACL context */ - rv = symTableAddSym(acc->acc_stp, &rdp->rd_sym, (void *)rdp); - if (rv) goto err_stadd; - - /* Add the right definition to the list for the ACL context */ - acc->acc_rights = rdp; - - /* Indicate a new right definition was created */ - rv = 1; - } - - /* Return a pointer to the RightDef_t structure if indicated */ - if (prd != 0) *prd = rdp; - - return rv; - - err_nomem: - eid = ACLERR3600; - rv = ACLERRNOMEM; - nserrGenerate(errp, rv, eid, ACL_Program, 0); - goto punt; - - err_stadd: - FREE(rdp->rd_sym.sym_name); - FREE(rdp); - eid = ACLERR3620; - rv = ACLERRDUPSYM; - nserrGenerate(errp, rv, eid, ACL_Program, 1, rname); - - punt: - return rv; -} - -/* - * Description (aclRightSpecDestroy) - * - * This function destroys a RightSpec_t structure. - * - * Arguments: - * - * rsp - pointer to RightSpec_t structure - */ - -void aclRightSpecDestroy(RightSpec_t * rsp) -{ - if (rsp != 0) { - - UILFREE(&rsp->rs_list); - - if (rsp->rs_sym.sym_name != 0) { - FREE(rsp->rs_sym.sym_name); - } - - FREE(rsp); - } -} - -/* - * Description (aclUserSpecCreate) - * - * This function allocates and initializes a new UserSpec_t - * structure, representing a list of users and groups. - * - * Arguments: - * - * None. - * - * Returns: - * - * If successful, the return value is a pointer to a new UserSpec_t. - * Otherwise the return value is null. - */ - -UserSpec_t * aclUserSpecCreate() -{ - UserSpec_t * usp; - - usp = (UserSpec_t *) MALLOC(sizeof(UserSpec_t)); - if (usp != 0) { - memset((void *)usp, 0, sizeof(UserSpec_t)); - usp->us_sym.sym_type = ACLSYMUSER; - } - - return usp; -} - -/* - * Description (aclUserSpecDestroy) - * - * This function destroys a UserSpec_t structure. - * - * Arguments: - * - * usp - pointer to UserSpec_t structure - */ - -void aclUserSpecDestroy(UserSpec_t * usp) -{ - if (usp != 0) { - - UILFREE(&usp->us_user.uu_user); - UILFREE(&usp->us_user.uu_group); - - if (usp->us_sym.sym_name != 0) { - FREE(usp->us_sym.sym_name); - } - - FREE(usp); - } -} |