Provided by: dacs_1.4.40-2_amd64 bug

NAME

       dacs.acls - DACS access control rules

DESCRIPTION

       These files are part of the DACS suite.

       When DACS receives a service request, expressed as a URL (see RFC 1738[1], RFC 2396[2],
       and RFC 3986[3]), it invokes ACS (its access control service, dacs_acs(8)[4]) to determine
       whether the request should be carried out.  ACS defines a language in which access control
       specifications are written to describe the conditions under which access to a resource is
       to be granted or denied.

       When it is invoked, ACS is provided with the service request URI, its parameters (if any),
       the current credentials of the client, and certain environment-dependent variables. A
       simple protocol defines how the web server passes this information to ACS and how ACS
       passes its access control decision back to the web server (see dacs_acs(8)[4]).

       If access is not revoked for the client, ACS proceeds to search for an applicable ACL rule
       for the given request and client. It first searches through custom files (those configured
       for the jurisdiction through the virtual filestore's item type "acls"); if necessary, it
       will also look through a set of standard access control rules (those configured through
       the virtual filestore's item type "dacs_acls") in an attempt to find a closer match.

       This document describes access control rules and the DACS authorization procedure.

           Tip
           The dacsacl(1)[5] command is used to validate the syntax of the rulesets and to
           rebuild indexes. After changing a ruleset by adding, removing, or modifying a rule,
           dacsacl(1)[5] must be run.

   Revoking Access and Disabling Authentication: The Revocation List
       It is sometimes useful to have the administrative capability to "pull the plug" on a
       particular user, class of users, or depending on other context. This can be done in a
       "global" way by configuring a revocation list. The revocation list is consulted during
       authorization checking and by various authentication related components. The revocation
       list is processed by dacs_acs(8)[4] before the rulesets, thereby overriding all access
       control rules, to see if a request should be denied based on the current credentials (if
       any) associated with the user making the request. The revocation list is also used by
       dacs_authenticate(8)[6], dacs_auth_transfer(8)[7], and dacs_auth_agent(8)[8] immediately
       after a tentatively successful authentication to check if access has been revoked for the
       DACS identity established through the normal authentication procedure. Note that the
       revocation list is not used by dacsauth(1)[9] or dacscheck(1)[10] (although it arguably it
       should be, at least optionally).

       A revocation list must be configured through the item type "revocations" and must be
       readable, although it can be empty.

       The list consists of a sequence of lines, evaluated in the order in which they appear,
       each of which may contain:

       •   deny expression

           If the expression[11] evaluates to True, 1) access is denied and the user's request is
           not performed and 2) revocation list processing terminates

       •   revoke expression

           The expression[11] is evaluated once for each set of credentials; if the expression
           evaluates to True, 1) those credentials will be ignored in all subsequent processing
           of the current request (as if they did not exist), including the remainder of
           revocation list processing, 2) access is not necessarily denied, and 3) revocation
           list processing continues with the next line; in the case of an unauthenticated user,
           revoke has the same meaning as deny. Revoking all credentials makes the user
           unauthenticated with respect to this request. Note that this revocation does not
           affect any credentials held by the user, it only temporarily "hides" them.

               Note
               It is not currently possible to construct a single expression that tests multiple
               credentials. If this creates difficulties, consider using the
               ACS_CREDENTIALS_LIMIT[12] or AUTH_SINGLE_COOKIE[13] directive.

       •   disable expression

           The expression[11] is evaluated in a context that includes the tentative credentials.
           If it evaluates to True, the account is deemed to be disabled and the credentials will
           not be issued. This is the only keyword used specifically for disabling authentication
           and is ignored during access control processing.

       •   block expression

           This form combines deny and disable behaviour to both deny access and disable
           authentication, effectively blocking all access that satisfies the expression[11].

       •   a comment, where the first non-whitespace character, if any, is a '#'

       The keywords are case insensitive and one or more whitespace characters appear between a
       keyword and the expression. A line can be continued by ending it with a backslash. Any
       line may be preceded by whitespace characters.

       DACS expressions are described in dacs.exprs(5)[11].

       Examples:

           # Deny access to all
           deny user("any")

           # Deny access to any user not already authenticated
           # (subsequently no one will be able to authenticate)
           deny user("unauth")

           # Revoke all identities, making all users effectively unauthenticated
           revoke user("any")

           # Deny access to any user not authenticated by this jurisdiction
           deny user("unauth") or not user("${Conf::JURISDICTION_NAME}:")

           # Revoke the identity DSS:rmorriso
           revoke user("DSS:rmorriso")

           # Deny all access on the weekend
           deny time("wday") eq 6 or time("wday") eq 0

           # Deny any request not originating from a local network
           deny not (from("10.0.0.0/8") or from("192.168.2.0/24"))

           # Do not issue credentials to anyone from 10.0.0.124 but access is
           # still possible
           disable from("10.0.0.124")

           # Do not issue credentials to DSS:bobo
           disable user("DSS:bobo")

           # Neither issue credentials nor grant access to DSS:bobo
           block user("DSS:bobo")

   URL Paths and Service Name Matching
       While matching a service request against ACL rules, ACS recognizes a hierarchical
       structure for service names based on the path component of an HTTP (or HTTPS) URL. The URL
       path "/cgi-bin", for example, is considered to be an ancestor or parent of the path
       "/cgi-bin/program". The former URL path has two components, the latter has three
       components. The one-component URL path "/" is considered to be the ancestor of all other
       paths.

       The * operator, which matches zero or more components that follow it, has special meaning
       only when it appears as a path component at the end of a URL path pattern specified by a
       rule. A system administrator can use the tail matching (wildcard) capability to establish
       default rules for portions of the name space of service requests. For instance the URL
       path pattern "/cgi-bin/*" is considered to be the ancestor of all paths having the prefix
       "/cgi-bin/" and matches service requests for "/cgi-bin/printenv", "/cgi-bin/", and
       "/cgi-bin".

       Before matching a service request against the ruleset, ACS converts the service request
       into a canonical form. It strips any trailing / characters off of the service name
       (although the URL path pattern "/" is unchanged). Only absolute URLs can be specified in
       an ACL rule. The URL expressing the service request must also be absolute when received by
       DACS; typically, a web server will canonicalize the pathname corresponding to static
       content before ACS is invoked.

           Note
           It is the URL-encoded request URI (passed by Apache as ${DACS::URI}) that is matched
           against access control rules. Path components of URLs used for matching in rules are
           URL-decoded before being compared against the path components of the request URI,
           which are also URL-decoded.

       ACS searches the ruleset for the rule having the most specific URL path pattern that
       applies to a given request URI; that is, it examines the rules to find the one that has
       the greatest number of components in common with the service request's. If no exact match
       is found, it will search for increasingly general rules that apply. Only the most specific
       matching rule will be applied to the request; if it fails, no other (less specific)
       matching rule will be considered. If two or more rules "tie" (e.g., because of duplicate
       rules), one rule will be chosen arbitrarily. If no suitable match if found, ACS will deny
       access.

           Note
           The URL path pattern may not contain a query component; this may be changed in future
           versions.

       ACS does not recognize alternate names for the same resource (e.g., achieved using
       symbolic links), so it is possible for each of several names for the identical resource to
       be associated with different access control rules.

           Security
           It is not necessarily the case that permission to access a parent or any ancestor is
           required to access a descendent path.

       It should be emphasized that the service request URL received by the web server is
       textually matched against ACL rules without any interpretation on the part of ACS. Other
       than whether it will be mapped to static content or a CGI program, what the URL represents
       or how it will be processed by the web server is not taken into account by ACS.

       For example, a service request for "/weekly" is not the same as a service request for
       "/weekly/index.html", even if "/weekly" is a directory and the web server would map the
       request to a file named "/weekly/index.html" and return its contents. A rule with the URL
       path pattern "/weekly/index.html" or "/weekly/*" (or perhaps "/*") is needed to control
       access to the file "/weekly/index.html".

   Service Parameters
       A user agent may optionally pass parameters to CGI programs. With the HTTP GET method, the
       parameters are appended to the URL sent to the web server (the "query string") and the CGI
       program. While the HTTP specification (RFC 2616[14]) does not impose a limit on the length
       of a URL, a browser or web server may impose a maximum. (Recent versions of Internet
       Explorer have a maximum URL length of 2,083 bytes and the Apache web server imposes a
       limit of about 8192 bytes.) In the case of the HTTP POST method, the parameters are
       streamed from the user agent to the web server and then to the CGI program, so the
       potential number of parameters and their combined size is unbounded.  ACS can optionally
       provide a finer granularity of access control by inspecting the parameters passed with a
       service request. By examining parameters, an ACL rule can be used to prevent certain users
       from gaining particular kinds of access. A rule might restrict a parameter value to be
       within a certain allowed range, for example.  ACS supports expressions that may test
       whether particular service parameters are present or reference their values.

       Because in the case of the POST method it is impractical, in general, to pass ACS all
       parameters and their values, a web server may impose limits on the number of parameters
       and aggregate size of parameters that it will make available to ACS. An invoked CGI
       program is unaffected by this limitation, however.  Apache's mod_auth_dacs[15] module
       allows its administrator to configure the maximum size of parameter data provided by the
       POST method that is made available to ACS.

   Constraints
       In some cases, merely testing parameter values is insufficient to determine whether access
       should be granted. Consider the case where a service is a program, a request's parameters
       represent the coordinates of a geographic area to be displayed, and some areas are not to
       be shown to some users, perhaps because they are "top secret". Examination of the
       parameters alone may be insufficient to determine whether the area they describe is within
       such a restricted area and perhaps ought not to be displayed. That determination might
       also depend on the contents of a database or complex calculations, for example. It is,
       therefore, beyond the scope of ACS to make access control decisions in such cases.

       ACS addresses this problem by allowing constraints to be attached to an ACL rule and by
       passing them, and the identity of the client, to the service. A constraint may be thought
       of as a tag or additional argument that a service recognizes. If an ACL rule permits the
       service to be invoked, it is the responsibility of the service to take any constraints
       into consideration and make the final decision about granting access, which it is much
       better qualified to do than is ACS. In the case previously described, a constraint might
       notify the service that the particular user should be granted access only if the request
       does not involve a restricted area.

       Of course, the purpose and meaning of a constraint depends on the implementation of a
       particular service. Different services might interpret the same constraint in completely
       different ways. For example, a service that performs both read-only operations and update
       operations might be implemented to recognize the constraint string "read-only" as meaning
       that it should only perform read-only operations. Alternatively, that same service might
       instead handle a request accompanied by the constraint string "updates-allowed" by
       permitting any operation for the user making the request; the absence of that constraint
       would restrict its functionality to read-only operations.

       For additional detail, please refer to descriptions of the DACS_CONSTRAINT and
       DACS_DEFAULT_CONSTRAINT environment variables.

   ACL Files
       Each access control rule is stored in a virtual filestore under the item types acls and
       dacs_acls. The acls must be configured, and ordinarily consists of site-specific or
       jurisdiction-specific rules; the latter (dacs_acls) is optional and is intended to
       configure rules for the standard DACS web services.

       The default configuration (from site.conf-std) is:

           VFS "[acls]dacs-fs:${Conf::FEDERATIONS_ROOT}/\
           ${Conf::FEDERATION_DOMAIN}/${Conf::JURISDICTION_NAME}/acls"
           VFS "[dacs_acls]dacs-fs:${Conf::DACS_HOME}/acls"

       Most installations store ACLs as ordinary files. This is reflected in the default
       configuration directive shown above and is why they are imprecisely referred to as "ACL
       files".

           Tip
           To make upgrading easier, avoid adding access control rules to dacs_acls (default
           location: /usr/local/dacs/acls) or modifying the default rules for DACS web services
           that appear there. Instead, put all customizations where acls has been configured. By
           following this practice, your customizations will not be lost when you install a new
           version of DACS.

       ACL Naming
           The names of ACL files (more precisely, the names of items within a virtual filestore)
           follow a particular convention: they must begin with the characters "acl-" (note: the
           fourth character is a hyphen, not an underscore) and end with a period followed by an
           unsigned integer value. At least one character must appear between the prefix and the
           suffix that begins with the period character. For example, any of the following names
           might be used:

               acl-photos.0
               acl-photos.1
               acl-files.40

               Tip
               Although not currently enforced, an ACL file name should be composed of characters
               from the Portable Filename Character Set[16]: any alphanumeric character, period,
               hyphen, or underscore.

           An ACL file may be disabled (not used by ACS) if a valid ACL filename is preceded by
           the characters "disabled-". The three ACLs above would be disabled if they were
           renamed as follows:

               disabled-acl-photos.0
               disabled-acl-photos.1
               disabled-acl-files.40

               Note
               These two filename prefixes are defined at compile time.  dacsacl(1)[5] should be
               enhanced to notice simultaneously enabled and disabled files.  FedAdmin, a
               contributed resource[17], is an administrative interface that can manage ACLs,
               including enabling, disabling, fetching, and deleting them.

           The numeric suffix is significant. It is used to order the evaluation of the rules by
           the access control service; the rules are evaluated in ascending order.

           Optionally, "subdirectories" (to any depth) can be created to help organize the access
           control rules. The naming convention for these subdirectories is the same as for ACL
           files. Disabling a subdirectory effectively disables all ACL files and subdirectories
           beneath it. The ordering process at each level is still based on the integer suffixes.
           Here is an example ordering of access control rules, from first to last:

               /usr/local/dacs/federations/dss/acls/acl-x.0
               /usr/local/dacs/federations/dss/acls/acl-x.2
               /usr/local/dacs/federations/dss/acls/acl-x.3/acl-y.7
               /usr/local/dacs/federations/dss/acls/acl-x.4
               /usr/local/dacs/federations/dss/acls/acl-x.5
               /usr/local/dacs/federations/dss/acls/acl-x.6/acl-x.1

           All ACL files and subdirectories that have invalid names are silently ignored, as are
           all files that are not regular files or directories (e.g., symbolic links). The
           behaviour is undefined if, for example, files named "acl-foo.0" and
           "disabled-acl-foo.0" exist simultaneously.

               Note
               Access control rules are ordinarily not placed in a location where a web server
               could serve them. If access control rules are themselves DACS-wrapped, however,
               care must be taken to structure the rules to avoid an infinite regress.

   ACL Syntax
       Basically, an ACL rule compactly expresses the triple (What, Who, How).

       What:
           the names of one or more services the rule applies to;

       Who
           the set of users the rule applies to; and

       How
           predicates and constraints that describe the conditions under which access will be
           allowed.

       Although it's certainly possible to write complicated access control rules, you needn't be
       intimidated. Rules are typically quite simple and easy to understand, such as the
       following rule which applies to a URL that has a path component ending in
       /cgi-bin/dacs/myprog.php and grants access to any authenticated user:

           <acl_rule status="enabled">
             <services>
               <service url_pattern="/cgi-bin/dacs/myprog.php"/>
             </services>

             <rule order="allow,deny">
                <allow>
                  user("auth")
                </allow>
             </rule>
           </acl_rule>

       An access control rule is written and stored externally as an XML document with the
       following DTD (acl.dtd[18]). Management of ACL rules can be done using a standard text
       editor, web-based interface, or special-purpose GUI. An administrator might only see a
       user-friendly description of the rules and need never see a lower-level representation
       such as this XML representation.

           <!ELEMENT acl_rule (services, (identity)*, (rule)+)>
           <!ATTLIST acl_rule
             status (enabled | disabled)             #IMPLIED
             name CDATA                              #IMPLIED
             expires_expr CDATA                      #IMPLIED
             constraint CDATA                        #IMPLIED
             permit_chaining (yes | no)              #IMPLIED
             pass_credentials (none | matched | all) #IMPLIED
             pass_http_cookie (yes | no)             #IMPLIED
             permit_caching (yes | no)               #IMPLIED
           >

           <!ELEMENT services (service | delegate)+>
           <!ATTLIST services
               shared (yes | no) #IMPLIED
           >

           <!ELEMENT service EMPTY>
           <!ATTLIST service
               id          CDATA #IMPLIED
               url_pattern CDATA #IMPLIED
               url_expr    CDATA #IMPLIED
           >

           <!ELEMENT delegate EMPTY>
           <!ATTLIST delegate
               id          CDATA #IMPLIED
               url_pattern CDATA #IMPLIED
               url_expr    CDATA #IMPLIED
               rule_uri    CDATA #REQUIRED
           >

           <!ELEMENT identity EMPTY>
           <!ATTLIST identity
               id            CDATA #IMPLIED
               iptr          CDATA #REQUIRED
               ident         CDATA #REQUIRED
               selector_expr CDATA #REQUIRED
           >

           <!ELEMENT rule ((precondition)?, (allow | deny)*) >
           <!ATTLIST rule
               id CDATA                                #IMPLIED
               order CDATA #REQUIRED
               <!-- order is either of: "allow,deny" or "deny,allow" -->
               constraint CDATA                        #IMPLIED
               permit_chaining (yes | no)              #IMPLIED
               pass_credentials (none | matched | all) #IMPLIED
               pass_http_cookie (yes | no)             #IMPLIED
               permit_caching (yes | no)               #IMPLIED
           >

           <!ELEMENT precondition ((user_list)?, (predicate)?)>

           <!ELEMENT user_list (user)*>

           <!ELEMENT user EMPTY>
           <!ATTLIST user
               id   CDATA #IMPLIED
               name CDATA #REQUIRED
           >

           <!ELEMENT predicate (#PCDATA)>

           <-- The allow element allows (grants) access, subject to the -->
           <-- allow,deny/deny,allow order, if the enclosed expression is TRUE -->
           <-- Note: any '<' and '&amp;' characters appearing within an allow element -->
           <-- must be escaped as &lt; and &amp;, respectively -->

           <!ELEMENT allow (#PCDATA)>
           <!ATTLIST allow
               id CDATA                                #IMPLIED
               constraint CDATA                        #IMPLIED
               permit_chaining (yes | no)              #IMPLIED
               pass_credentials (none | matched | all) #IMPLIED
               pass_http_cookie (yes | no)             #IMPLIED
               permit_caching (yes | no)               #IMPLIED
           >

           <-- The deny element denies access, subject to the allow,deny/deny,allow -->
           <-- order, if the enclosed expression is TRUE -->
           <-- Note: any '<' and '&amp;' characters appearing within an allow element -->
           <-- must be escaped as &lt; and &amp;, respectively -->

           <!ELEMENT deny (#PCDATA)>
           <!ATTLIST deny
               id CDATA                                #IMPLIED
           >

       The optional id attribute assigns a unique label (within its acl_rule) to an element so
       that it can be identified conveniently and unambiguously. Attribute values consist of one
       or more alphanumerics and underscores. At present, no other semantics are assigned to this
       attribute, but this may change in future releases. Labels that begin with an underscore
       are reserved for DACS-generated labels.

       General Structure
           An access control rule can be divided into two parts: an ordered list of service
           specifications (the services element) that are matched against service requests, and
           an ordered list of rule specifications (the rule elements) that are processed if and
           only if one of the service elements is applicable. In the event that the access
           control rule grants access, various aspects of subsequent processing can be controlled
           and defaults can be established.

       Services
           This part of the rule is used during rule selection. Each service element specifies a
           service to which this access control rule applies. The delegate element identifies a
           service that is handled by an access control rule specified elsewhere. Delegation is
           useful if parts of the URL space are managed by different users or if rules are stored
           in different locations.

       Rule Clause Processing
           An access control rule consists of one or more rule elements, also called rule
           clauses. A rule clause consists of allow and deny elements. The allow element allows
           (grants) access if the enclosed expression[11] is True, subject to the rule's order
           attribute. The deny element denies access if the enclosed expression is True, subject
           to the rule's order attribute.

           Each rule must have an order attribute that says whether the evaluation order is
           "allow,deny" or "deny,allow". This attribute serves much the same purpose as, and has
           semantics similar to, the Apache mod_authz_host[19] module's Order directive.

           The allow,deny ordering denies access by default and causes allow elements to be
           evaluated before deny elements. A request that does not satisfy an allow element or
           does satisfy a deny element will be denied. Equivalently, a request must satisfy an
           allow element but not satisfy any deny element for access to be granted. If a rule
           element has no allow element, it is processed as if it had an allow element that
           evaluated to False. If a rule element has no deny element, access is granted only if
           an allow element evaluates to True.

           The deny,allow ordering permits access by default and causes deny elements to be
           evaluated before allow elements. A request that does not satisfy a deny element or
           does satisfy an allow element will be allowed. Equivalently, a request must satisfy a
           deny element but not satisfy any allow element for access to be denied. If a rule
           element has no deny element, it is processed as if it had an deny element that
           evaluated to False. If a rule element has no allow element, access is granted only if
           no deny element evaluated to True.

           As soon as one allow (deny) element evaluates to True, no other elements of the same
           type are evaluated.

               Note
               Any '<' and '&' characters appearing within an allow element or a deny element
               must be escaped as "&lt;" and "&amp;", respectively.

       The Precondition Element
           A rule may optionally have exactly one precondition element. The precondition element
           is a "guard" to enable or disable a particular rule. This might be used, for example,
           to write one rule for weekdays and another for weekends. It can specify a list of
           users, an expression[11], or both. For the rule to be enabled for evaluation, its
           expression must first evaluate to True; if the user_list element is present, the user
           making the request must be among those listed and if the predicate is present, it must
           evaluate to True. The precondition primarily serves three purposes:

            1. it can make it clear which user(s) the rule applies to;

            2. it can improve by efficiency by avoiding having to evaluate potentially expensive
               expressions; and

            3. it provides a way to have multiple rule elements, any of which might be enabled
               depending on the run-time context.

       Expressions
           DACS employs expressions in access control rules and in configuration files (see
           dacs.exprs(5)[11]). For example, an expression or sequence of statements may appear
           within predicate, allow, and deny elements of an access control rule. If an expression
           (or sequence) evaluates to zero, the null string, or an error occurs, the result is
           False. If it evaluates to non-zero or a non-null string and no error occurs, the
           result of the expression (or sequence) is True. In general, arithmetic overflow and
           underflow, rounding, and other similar conditions will not be detected or considered
           as errors.

           The particular context within which a service request is being evaluated is made
           available to an expression through a set of variables. They are described with the
           dacs_acs(8)[4].

           Rules are examined in the order in which they are specified. If a precondition is
           False, processing continues with the next rule. The first rule with a True
           precondition will be used; no other rule will be examined. If no precondition element
           is given for a rule, it is equivalent to a precondition that evaluates to True. If no
           rule satisfies its precondition, access is denied.

       ACL Rule Elements
           The various syntactical components of access control rules are now described. When a
           request is being processed, ACS examines a ruleset, which is a collection of acl_rule
           elements that are located and accessed depending on the jurisdiction's configuration.

           DACS expressions are described in dacs.exprs(5)[11].

           acl_rule

                   <!ELEMENT acl_rule (services, (identity)*, (rule)+)>
                   <!ATTLIST acl_rule
                     status (enabled | disabled)             #IMPLIED
                     name CDATA                              #IMPLIED
                     expires_expr CDATA                      #IMPLIED
                     constraint CDATA                        #IMPLIED
                     permit_chaining (yes | no)              #IMPLIED
                     pass_credentials (none | matched | all) #IMPLIED
                     pass_http_cookie (yes | no)             #IMPLIED
                     permit_caching (yes | no)               #IMPLIED
                   >

               An acl_rule specifies, for a given set of services, the conditions under which a
               request for one of those services is to be granted (or denied). It may also
               establish new default behaviours (overriding compile-time or configuration
               defaults) that will be used unless they are in turn overridden during processing
               of this rule. The name attribute can be used to assign a symbolic name to the
               rule; some programs (e.g., dacsrlink(1)[20]) use this name to catch errors. The
               expires_expr attribute determines if the ACL should be ignored (and potentially
               deleted, although no DACS programs currently implement this). If the expression
               expires_expr evaluates to True, the rule should be deleted.

           identity

                   <!ELEMENT identity EMPTY>
                   <!ATTLIST identity
                       id            CDATA #IMPLIED
                       iptr          CDATA #REQUIRED
                       ident         CDATA #REQUIRED
                       selector_expr CDATA #REQUIRED
                   >

               This element associates a specified identity (ident) with the request during
               processing of this acl_rule only. This "assigned identity" overrides any identity
               or identities that were submitted with the request and is not tested for
               revocation. The iptr attribute is essentially a unique label for this element.

               The identity elements are examined, in the order in which they appear, until one
               element is selected; no other elements will be processed. An element is selected
               if its attribute (selector_expr), which is an expression[11], evaluates to True,
               in which case the identity specified by the ident attribute is used; its value
               must be a syntactically valid identity in the concise user syntax[21]. Access will
               be denied if an invalid identity is produced, and rule processing will proceed
               normally if no element is selected.

               The primary purpose of this element is to support an operational mode of the
               Rlinks[22] feature, but the capability may eventually be generalized. This element
               is subject to change. A future enhancement may allow the identity to alternatively
               be determined by expression evaluation.

           services

                   <!ELEMENT services (service | delegate)+>
                   <!ATTLIST services
                       shared (yes | no) #IMPLIED
                   >

               This element groups service and delegate elements.

           service

                   <!ELEMENT service EMPTY>
                   <!ATTLIST service
                       id          CDATA #IMPLIED
                       url_pattern CDATA #IMPLIED
                       url_expr    CDATA #IMPLIED
                   >

               To decide whether this acl_rule might apply to a request, ACS examines the set of
               one or more service elements. Each service element has either a url_pattern
               attribute or a url_expr attribute (but not both); the only difference is that the
               url_expr attribute is an expression[11] that is evaluated and converted to a
               string that is used internally as the url_pattern (it is a fatal error if the
               evaluation results in an error or the null string). Each effective url_pattern,
               whether given as a url_pattern attribute value or derived from a url_expr, is a
               simple pattern that may be matched against the URL of a service request. With the
               exception of the special '*' pattern, an effective url_pattern must begin with a
               '/'; its last component may be a '/*' to indicate that the pattern matches zero or
               more components of the service request URL that follow.

               The special '*' pattern always results in a successful exact match, causing rule
               searching to terminate immediately. It is useful as the value of a url_expr that
               has determined that its rule should be selected. Note that the semantics of this
               pattern are different from those of the pattern '/*', which results in a
               successful match only if no closer match is found.

               During matching, the URL of the service request is first stripped up to and
               including the hostname part, and parameters, if any, are excluded (starting with a
               '?' character and extending to the end). Any trailing '/' characters are removed.

               Consider the service request "/cgi-bin/metalogic/metalogic_groups" being matched
               against the following set of service elements:

                1. <service url_pattern="/*"/>

                2. <service url_pattern="/cgi-bin/*"/>

                3. <service url_pattern="/cgi-bin/metalogic/*"/>

                4. <service url_pattern="/cgi-bin/metalogic/metalogic_groups"/>

                5. <service url_pattern="/tmp/foo.gif"/>

               The first four prefixes match the service request URL, but the fourth url_pattern
               is selected since it is the most specific match, with the third url_pattern being
               the next most specific match.

               When a single site is home to more than one jurisdiction, it is often handy to be
               able to share access control rules among the jurisdictions. The shared attribute
               controls this behaviour. This is best described through an example. Consider the
               following (partial) Jurisdiction sections:

                   <Jurisdiction uri="dss.ca">
                     JURISDICTION_NAME "ANIMAL"
                   </Jurisdiction>

                   <Jurisdiction uri="dss.ca/dog">
                     JURISDICTION_NAME "DOG"
                   </Jurisdiction>

                   <Jurisdiction uri="dss.ca/cat">
                     JURISDICTION_NAME "CAT"
                   </Jurisdiction>

               With this feature enabled for a set of services, a request for dss.ca/cat/foo...
               will only consider the /foo...  substring when searching the url_pattern
               attributes to find a matching rule.

               The syntax for the shared attribute is as follows:

                   <!-- Share all services among -->
                   <!-- path-differentiated jurisdictions -->
                   <services shared="yes">

                   <!-- Do not share services among -->
                   <!-- path-differentiated jurisdictions -->
                   <services shared="no">

                   <!-- Default: share all services among -->
                   <!-- path-differentiated jurisdictions -->
                   <services>

               Here are some examples, given the configuration above:

                   Partial request URI                 Matched url_pattern

                   dss.ca/cgi-bin/dacs/dacs_prenv      -->  /cgi-bin/dacs/dacs_prenv
                   dss.ca/dog/cgi-bin/dacs/dacs_prenv  -->  /cgi-bin/dacs/dacs_prenv
                   dss.ca/cat/cgi-bin/dacs/dacs_prenv  -->  /cgi-bin/dacs/dacs_prenv

                   Tip
                   The default behaviour is the same as if shared="yes" were specified. When this
                   feature is enabled, dss.ca/cat/cgi-bin/dacs/dacs_prenv will not match
                   dss.ca/cgi-bin/dacs/dacs_prenv in the example configuration above.

                   The default rules for DACS services assume the default behaviour with respect
                   to sharing.

           delegate

                   <!ELEMENT delegate EMPTY>
                   <!ATTLIST delegate
                       id          CDATA #IMPLIED
                       url_pattern CDATA #IMPLIED
                       url_expr    CDATA #IMPLIED
                       rule_uri    CDATA #REQUIRED
                   >

               The delegate element functions exactly like the service element with respect to
               matching. Its purpose, however, is to redirect responsibility for subsequent
               access control processing for the request to another ruleset.

               There are many applications for this feature, but a common one is for a DACS
               administrator to "carve up" the URL space by delegating parts of it such that
               individual users are responsible for the rules governing their portion of the
               space. For example, URL paths that begin with /bob, /ted, and /ann might be
               delegated to rulesets found in /u/bob/.dacs/acls, /u/ted/.dacs/acls, and
               /u/ann/.dacs/acls, respectively, and a request like
               https://example.com/bob/index.html would be fielded by the ruleset found in
               /u/bob/.dacs/acls.

               If a delegate element is matched:

                1. no rule clauses in this access control rule will be examined

                2. any defaults specified in the acl_rule element will be discarded

                3. processing of the current ruleset is terminated

                4. the ruleset identified by the rule_uri attribute will be consulted

                5. no default system ACLs (dacs_acls) will be examined

               Processing of a delegated ruleset is performed in the same way as a non-delegated
               ruleset. A delegated ruleset may delegate some or all of its services to another
               ruleset; a maximum depth of three is enforced.

               Any error encountered during processing will cause access to be denied.

                   Note
                   Despite the attribute name, the value of the rule_uri attribute must currently
                   be a defined item type or a URL that identifies a directory or a supported
                   database (i.e., having a URL scheme of file, dacs-db, or dacs-ndbm) The
                   semantics of this attribute are still being considered.
               For example, an ACL with the elements:

                   <delegate url_pattern="/cgi-bin/myprog" rule_uri="my_acls"/>
                   <delegate url_pattern="/*" rule_uri="file:/u/bob/delegated"/>

               and the configuration:

                   VFS "[my_acls]dacs-db:/u/bob/my_acls.db"

               will delegate service requests matching the first element to rules found in the
               Berkeley DB file /u/bob/my_acls.db and all other service requests to a ruleset
               found in the directory /u/bob/delegated.

                   Security
                   Delegated access control rules have access to all functions (including exec())
                   and all configuration information. Note that dacs_acs runs at the privilege
                   level of Apache. For this reason, be very careful how delegation is used. Log
                   messages identify selection of delegated rules and can be used to detect
                   improper use. A future version of DACS should provide a way to optionally
                   restrict the abilities of delegated rules.

           rule

                   <!ELEMENT rule ((precondition)?, (allow | deny)*) >
                   <!ATTLIST rule
                       id CDATA                                #IMPLIED
                       order CDATA #REQUIRED
                       <!-- order is either of: "allow,deny" or "deny,allow" -->
                       constraint CDATA                        #IMPLIED
                       permit_chaining (yes | no)              #IMPLIED
                       pass_credentials (none | matched | all) #IMPLIED
                       pass_http_cookie (yes | no)             #IMPLIED
                       permit_caching (yes | no)               #IMPLIED
                   >

               Assuming that ACS has determined that this acl_rule is the one that best matches a
               request, it will then examine one or more of its rule elements and use the first
               one that has been enabled (that is, satisfies its precondition). An enabled rule
               element may establish new default behaviours (overriding compile-time,
               configuration, or acl_rule defaults) that will be used unless they are in turn
               overridden during processing of this rule.

               Information regarding rule clause processing[23] appeared earlier.

           precondition

                   <!ELEMENT precondition ((user_list)?, (predicate)?)>

               A precondition element is used to specify a set of users that includes the user
               making the request, a condition that must evaluate to True, or both.  ACS will
               examine the rule elements from top to bottom, selecting the first rule having a
               precondition that is satisfied. That rule is said to be enabled and no other rule
               will be considered. If no rule is enabled, access will be denied.

                   Note
                   A precondition element must contain a predicate element, a user_list element,
                   or both.

           user_list, user

                   <!ELEMENT user_list (user)*>

                   <!ELEMENT user EMPTY>
                   <!ATTLIST user
                       id   CDATA #IMPLIED
                       name CDATA #REQUIRED
                   >

               A user_list element consists of zero or more user elements, each of which has a
               name attribute that is matched against the client's current credentials. Please
               refer to the description of the user()[24] function for details. A user_list that
               is absent or empty is effectively one that satisfies the precondition. It does not
               matter to ACS whether a mentioned user, group, or jurisdiction actually exists or
               is defined.

               The following is an example of a user_list (group names are prefixed by a '%'
               character):

                   <user_list>
                      <user name="DSS:smith"/>
                      <user name="%METALOGIC:admin/>
                      <user name="10.0.0.118"/>
                      <user name="192.168.0.0/24"/>
                      <user name="DACS:"/>
                      <user name="unauth"/>
                   </user_list>

           predicate

                   <!ELEMENT predicate (#PCDATA)>

               A predicate contains an expression[11] (or sequence of statements) that is
               evaluated in the context of a particular request and client's current credentials.
               A predicate having no expression evaluates to True. Expressions are described with
               dacs.exprs(5)[11]).

           allow

                   <!ELEMENT allow (#PCDATA)>
                   <!ATTLIST allow
                       id CDATA                                #IMPLIED
                       constraint CDATA                        #IMPLIED
                       permit_chaining (yes | no)              #IMPLIED
                       pass_credentials (none | matched | all) #IMPLIED
                       pass_http_cookie (yes | no)             #IMPLIED
                       permit_caching (yes | no)               #IMPLIED
                   >

               An allow element contains an expression[11] (or sequence of statements) that is
               evaluated in the context of a particular request and client's current credentials.
               If it evaluates to True, an allow element may establish particular behaviours
               (overriding compile-time or configuration defaults or encompassing acl_rule or
               rule element defaults). Information regarding rule clause processing[23] appeared
               earlier.

           deny

                   <!ELEMENT deny (#PCDATA)>
                   <!ATTLIST deny
                       id CDATA                                #IMPLIED
                   >

               A deny element contains an expression[11] (or sequence of statements) that is
               evaluated in the context of a particular request and client's current credentials.
               Information regarding rule clause processing[23] appeared earlier.

           If ACS grants access, various aspects of subsequent behaviour can be controlled
           through attributes of acl_rule elements, with attributes specified at a "deeper" level
           overriding ones encountered earlier during ruleset processing.

           A constraint can optionally be specified. If access is granted and a constraint has
           been provided by the particular allow element that evaluated to True, it is made
           available as the value of an environment variable named DACS_CONSTRAINT exported to
           the invoked CGI program. If access is granted and a default constraint has been
           provided, it is similarly made available as the value of an environment variable named
           DACS_DEFAULT_CONSTRAINT. Neither variable is defined if no value for it has been
           specified.

           If access is granted, ACS can be told through the pass_credentials attribute whether
           it should pass the user's current credentials on to the invoked service. For security
           reasons, it does not pass credentials ("none") by default. It can be instructed to
           pass all current credentials ("all"); a service such as
           dacs_current_credentials(8)[25], for example, needs to receive all of the current
           credentials. A third alternative is to pass only the current credentials of the
           identity that was used to grant access by having satisfied a user element ("matched");
           in the case of multiple current credentials, it may not be possible to predict which
           current credentials will be matched. When permitted, credentials are passed in the
           same HTTP cookie format in which they were received as the value of the DACS_COOKIE
           environment variable.  DACS will look for the user's DACS cookies in that variable
           before checking the HTTP_COOKIE environment variable.

               Security
               Because environment variables are typically visible to all programs on a system,
               ACS "hobbles" or "weakens" credentials exported through them such that they can
               only be used in a few limited ways. Using them for access control purposes is not
               one of those ways, otherwise a DACS identity could easily be stolen by any user
               having access to the variables.

               In addition to the environment variable problem, a user might be tricked into
               invoking a service, though DACS-wrapped, that is under the control of an attacker.
               Weakening the credentials that are available to the service makes it difficult for
               the attacker to do any harm with them.

               A DACS administrator who understands the implications of visible credentials, and
               who still insists on proceeding at his own risk, can disable the DACS security
               measures by setting the permit_chaining attribute to yes. Any jurisdiction that
               should honor such credentials for access control purposes must set the
               configuration directive PERMIT_CHAINING[26] to yes. This will allow the
               credentials passed to a service invoked at that jurisdiction to be used for access
               control purposes. By default, this "chaining" or "cascading" behaviour is not
               permitted and the credentials are invalid for access control purposes.

               If the pass_credentials attribute is all or matched for the matching rule,
               unaltered credentials will be exported through the DACS_COOKIE environment
               variable.

           If access is granted, DACS can be told whether it should pass the Cookie header field
           to the invoked service. By default, pass_http_cookie is "no" to reduce the risk of
           cookies being exposed. Unless DACS has been configured with ALLOW_HTTP_COOKIE set to
           "yes", DACS services will refuse to operate if they receive a Cookie header field. If
           pass_http_cookie is "yes", however, the Cookie header field will be retained.

               Tip
               Setting pass_http_cookie to "yes" is often necessary in cases where Apache does an
               internal redirect, as when it invokes scripts through the Action[27] directive or
               when it automatically creates a directory index (as by the Indexes option of the
               Options[28] directive). If this attribute is not enabled, Apache will lose track
               of the identity associated with the request when the redirection occurs, and it
               will appear to DACS as if the user making the redirected request is not
               authenticated.

           The permit_caching attribute is used to indicate that positive access control
           decisions associated with the rule are eligible for caching. Please see Authorization
           Caching[29] for details.

           Groups are discussed in a separately in dacs.groups(5)[30].

   The ACL Selection and Evaluation Algorithm
       The following algorithm is used by ACS to determine if a particular service request (S, in
       canonical form) with optional parameters (P) should be granted for a user with verified
       credentials (C) within a particular execution environment (E). At this point, ACS has
       already determined that the revocation list has not denied access.

        1. ACS searches the ruleset for an acl_rule (R) that lists a service or delegation (using
           url_pattern or by evaluation of a url_expr) that most closely matches S. The list of
           services is examined in the order in which they appear.

           •   If any acl_rule matches exactly, it is selected and the search for an acl_rule is
               terminated; no other acl_rule in the current ruleset will be examined. Otherwise,
               the next acl_rule specification will be examined.

           •   The acl_rule elements in the ruleset are examined in increasing order of the
               integer suffix of each rule's name.

           •   A particular url_pattern should appear exactly once within the entire ruleset.

           ACS does not treat a duplicated url_pattern as an error, however, nor is it required
           to check for duplicates.

           If the closest match delegates responsibility to another ruleset, the procedure
           restarts by searching that ruleset.

        2. Each rule element in R is examined, from top to bottom, until all have been examined
           or until one is found that is enabled. An enabled rule either has no precondition
           element or has a precondition that evaluates to True. If an enabled rule is found, no
           other rule will be considered. If no enabled rule is found, access is denied.

           •   A precondition is True if the user is identified by a user element (or if there is
               no user_list element or no user element) and if the predicate element evaluates to
               True (or if there is no predicate element).

           •   During user_list processing, for each set of current credentials, the credentials
               are compared against the list of user elements in the order in which the user
               elements appear in the user_list.

           •   If there is more than one set of credentials accompanying the request, C is
               considered to be the union of all of the credentials.

           •   If the enabled rule specifies the order allow,deny, then allow elements are
               examined before deny elements; if the order is deny,allow, then deny elements are
               examined before allow elements.

           •   Evaluation of allow elements always stops when one evaluates to True.

           •   Evaluation of deny elements always stops when one evaluates to True.

           •   In the case of an allow,deny ordering, access is denied by default and allow
               elements are evaluated before deny elements; a request that does not satisfy an
               allow element or does satisfy a deny element will be denied.

           •   In the case of a deny,allow ordering, access is granted by default and causes deny
               elements to be evaluated before allow elements; a request that does not satisfy a
               deny element or does satisfy an allow element will be allowed.

           •   If any predicate evaluates to True, the user will be granted access to S with P.

        3. If access is granted, default or specific attributes associated with the matching
           acl_rule, rule, or allow elements will be passed to S.

           Security
           It is possible to construct rules such that more than one rule, allow, or deny element
           applies to a particular user or are contradictory. Such conditions are neither
           detected nor considered an error.

EXAMPLES

       For conciseness, some of the following examples omit the services element.

        1. This rule grants access to everyone because it establishes "allow" as the default and
           there is no satisfied deny element.

               <rule order="deny,allow"></rule>

        2. This rule denies access to everyone because it establishes "deny" as the default and
           there is no satisfied allow element.

               <rule order="allow,deny"></rule>

        3. This rule establishes the evaluation order allow,deny and there are two allow elements
           and no deny elements, which means that access will only be granted if one of the allow
           elements evaluates to True. The second allow element evaluates to True if 1) the
           variable SCALE is greater than 1000 and the user is authenticated or 2) the variable
           SCALE is greater than 10000 and the user is not authenticated.

               <rule order="allow,deny">
                 <allow>
                   user("METALOGIC:rmorriso") or user("DSS:brachman")
                 </allow>

                 <allow>
                   (${Args::SCALE} gt 1000 and user("auth"))
                      or (${Args::SCALE} gt 10000 and user("unauth"))
                 </allow>
               </rule>

           If the evaluation order deny,allow were selected instead, access would always be
           granted (since there is no deny element and the default is to grant access). If
           neither of the allow elements evaluates to True, however, default attributes (if
           present) would be in effect.

        4. If SCALE is less than 10000 and LAYER-ELEMENT is one of the listed layers and the user
           is not in the forest-inventory group, then deny. Otherwise, if the user is
           authenticated, allow.

               <rule order="allow,deny">
                 <deny>
                    ${Args::SCALE} lt 10000
                     and (${Args::LAYER-ELEMENT} eq "BC_ORTHO"
                     or ${Args::LAYER-ELEMENT} eq "BC_FC50K"
                     or ${Args::LAYER-ELEMENT} eq "AB_FC50K"
                     or ${Args::LAYER-ELEMENT} eq "SK_FC50K"
                     or ${Args::LAYER-ELEMENT} eq "MV_FC50K")
                     and (not user("%METALOGIC:forest-inventory-"))
                 </deny>

                 <allow>
                   user(auth)
                 </allow>
               </rule>

        5. The first of these rules is selected only for requests coming from members of the
           group METALOGIC:forest-inventory. Access is granted to any member, except
           METALOGIC:rmorriso. The second of these rules is selected for requests not coming from
           members of that group. Access is granted only if the condition is True.

               <rule order="allow,deny">
                 <precondition>
                   <user_list>
                     <user name="%METALOGIC:forest-inventory"/>
                   </user_list>
                 </precondition>

                 <allow>
                   not user("METALOGIC:rmorriso")
                 </allow>
               </rule>

               <rule order="allow,deny">
                 <allow>
                   ( ${Args::SCALE} gt 1000 and user("auth") )
                     or ( ${Args::SCALE} gt 10000 and user("unauth") )
                 </allow>
               </rule>

           If the first rule's precondition were instead:

               <precondition>
                 <predicate>
                   user("%METALOGIC:forest-inventory") and user("DSS:")
                 </predicate>
               </precondition>

           then the first rule would only be considered if the user belonged to that group and he
           was authenticated by the DSS jurisdiction.

        6. This rule establishes a default for all CGI programs under the cgi-bin URL space. Only
           users authenticated by the jurisdiction METALOGIC will have access and CGI programs
           will be invoked with the environment variable DACS_DEFAULT_CONSTRAINT set to
           "MODE=execute-only".

               <acl_rule status="enabled" constraint="MODE=execute-only">
                  <services>
                    <service url_pattern="/cgi-bin/*"/>
                  </services>
                  <rule order="allow,deny">
                    <precondition>
                      <user_list>
                        <user name="METALOGIC:"/>
                      </user_list>
                    </precondition>
                    <allow>
                    </allow>
                  </rule>
               </acl_rule>

        7. This rule establishes a default behaviour that denies all access.

               <acl_rule status="enabled">
                 <services>
                    <service url_pattern="/*"/>
                 </services>
                 <rule order="allow,deny">
                   <deny>
                   </deny>
                 </rule>
               </acl_rule>

        8. This rule establishes a default behaviour that grants access to the URL space under
           /any-user to any authenticated user. CGI programs will be invoked with the environment
           variable DACS_CONSTRAINT set to "read-only".

               <acl_rule status="enabled">
                 <services>
                    <service url_pattern="/any-user/*"/>
                 </services>
                 <rule order="allow,deny">
                    <allow constraint="read-only">
                      user("auth")
                    </allow>
                 </rule>
               </acl_rule>

        9. This rule establishes a default for all CGI programs under the cgi-bin/gis and
           cgi-bin/metalogic URL space. Access is granted to members of the groups BC:gis and
           NF:gis only if the value of parameter X is greater than 10 and the value of parameter
           Y is greater than 17. CGI programs invoked by those users will have the environment
           variable DACS_DEFAULT_CONSTRAINT set to "MODE=read-only". Members of the group ON:gis
           have no constraints on the parameters and will invoke CGI programs with the
           environment variable DACS_CONSTRAINT set to "read-write". Requests that do not meet
           either allow element will be denied.

               <acl_rule status="enabled" constraint="read-only">
                 <services>
                    <service url_pattern="/cgi-bin/gis/*"/>
                    <service url_pattern="/cgi-bin/metalogic/*"/>
                 </services>

                 <rule order="allow,deny">
                   <allow>
                     ${Args::X} gt 10 and ${Args::Y} gt 17
                        and (user("%BC:gis") or user("%NF:gis")
                   </allow>

                   <allow constraint="read-write">
                      user("%ON:gis")
                   </allow>
                 </rule>
               </acl_rule>

       10. Only bob@dss.ca, authenticated by jurisdiction DSS, will have access to the service
           /cgi-bin/bob-prog.cgi.

               <acl_rule status="enabled">
                  <services>
                    <service url_pattern="/cgi-bin/bob-prog.cgi"/>
                  </services>

                  <rule order="allow,deny">
                    <allow>
                      user("DSS:bob@dss.ca")
                    </allow>
                  </rule>
               </acl_rule>

       11. Every user will be able to invoke the service /cgi-bin/metalogic/group if CGI
           parameter OP is LIST_GROUPS or SHOW_GROUP. If OP is ADD_GROUP, DELETE_GROUP, or
           MODIFY_GROUP, only a member of the group DSS:admin can invoke the program. String
           comparisons are performed without regard to case. If OP has any other value, access
           will be denied.

               <acl_rule status="enabled">
                  <services>
                    <service url_pattern="/cgi-bin/metalogic/group"/>
                  </services>

                  <rule order="allow,deny">
                    <allow>
                      ${Args::OP} eq:i "LIST_GROUPS"
                         or ${Args::OP} eq:i "SHOW_GROUP"
                    </allow>

                    <allow>
                      (${Args::OP} eq:i "ADD_GROUP"
                         or ${Args::OP} eq:i "DELETE_GROUP"
                         or ${Args::OP} eq:i "MODIFY_GROUP")
                         and user("%DSS:admin")
                    </allow>
                 </rule>
               </acl_rule>

SEE ALSO

       dacsacl(1)[5], dacs_admin(8)[31]

AUTHOR

       Distributed Systems Software (www.dss.ca[32])

COPYING

       Copyright © 2003-2017 Distributed Systems Software. See the LICENSE[33] file that
       accompanies the distribution for licensing information.

NOTES

        1. RFC 1738
           http://www.rfc-editor.org/rfc/rfc1738.txt

        2. RFC 2396
           http://www.rfc-editor.org/rfc/rfc2396.txt

        3. RFC 3986
           http://www.rfc-editor.org/rfc/rfc3986.txt

        4. dacs_acs(8)
           http://dacs.dss.ca/man/dacs_acs.8.html

        5. dacsacl(1)
           http://dacs.dss.ca/man/dacsacl.1.html

        6. dacs_authenticate(8)
           http://dacs.dss.ca/man/dacs_authenticate.8.html

        7. dacs_auth_transfer(8)
           http://dacs.dss.ca/man/dacs_auth_transfer.8.html

        8. dacs_auth_agent(8)
           http://dacs.dss.ca/man/dacs_auth_agent.8.html

        9. dacsauth(1)
           http://dacs.dss.ca/man/dacsauth.1.html

       10. dacscheck(1)
           http://dacs.dss.ca/man/dacscheck.1.html

       11. expression
           http://dacs.dss.ca/man/dacs.exprs.5.html

       12. ACS_CREDENTIALS_LIMIT
           http://dacs.dss.ca/man/dacs.conf.5.html#ACS_CREDENTIALS_LIMIT

       13. AUTH_SINGLE_COOKIE
           http://dacs.dss.ca/man/dacs.conf.5.html#AUTH_SINGLE_COOKIE

       14. RFC 2616
           http://www.rfc-editor.org/rfc/rfc2616.txt

       15. mod_auth_dacs
           http://dacs.dss.ca/man/mod_auth_dacs.html

       16. Portable Filename Character Set
           http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276

       17. contributed resource
           http://sourceforge.net/projects/dacs-contrib/

       18. acl.dtd
           http://dacs.dss.ca/man/../dtd-xsd/acl.dtd

       19. mod_authz_host
           http://httpd.apache.org/docs/2.4/mod/mod_authz_host.html

       20. dacsrlink(1)
           http://dacs.dss.ca/man/dacsrlink.1.html

       21. concise user syntax
           http://dacs.dss.ca/man/dacs.1.html#concise_user_syntax

       22. Rlinks
           http://dacs.dss.ca/man/dacs_acs.8.html#rlinks

       23. rule clause processing
           http://dacs.dss.ca/man/#ordering

       24. user()
           http://dacs.dss.ca/man/dacs.exprs.5.html#user

       25. dacs_current_credentials(8)
           http://dacs.dss.ca/man/dacs_current_credentials.8.html

       26. PERMIT_CHAINING
           http://dacs.dss.ca/man/dacs.conf.5.html#PERMIT_CHAINING

       27. Action
           http://httpd.apache.org/docs/2.4/mod/mod_actions.html#action

       28. Options
           http://httpd.apache.org/docs/2.4/mod/core.html#options

       29. Authorization Caching
           http://dacs.dss.ca/man/dacs_acs.8.html#authorization_caching

       30. dacs.groups(5)
           http://dacs.dss.ca/man/dacs.groups.5.html

       31. dacs_admin(8)
           http://dacs.dss.ca/man/dacs_admin.8.html

       32. www.dss.ca
           http://www.dss.ca

       33. LICENSE
           http://dacs.dss.ca/man/../misc/LICENSE