Provided by: dacs_1.4.28b-3ubuntu1_amd64 bug

NAME

       dacscheck - authorization check

SYNOPSIS

       dacscheck [-admin] [-app appname] [-context file] [-Dname=value]
                 [-F field_sep] [-fd domain] [-fh hostname] [-fj jurname] [-fn fedname]
                 [-dump] [-groups group_vfs] [-h] [-i ident] [-il ident]
                 [-ilg ident] [-ieuid] [-ieuidg] [-iuid] [-iuidg] [-lg] [-ll log_level]
                 [-name_compare method] [-q]
                 [-redirect] [-roles roles_vfs] [-rules rule_vfs] [-v] [-var name=value]
                 [-vfs vfs_uri] [--] object

DESCRIPTION

       This program is part of the DACS suite. It is a stand-alone program that neither accepts
       the usual DACS command line options (dacsoptions) nor accesses any DACS configuration
       files.

       Put simply, dacscheck looks at access control rules to test if a given user is authorized
       to do something or access something. The command's exit status gives the result of the
       test, and unless the -q flag is given, a line is printed to stdout that indicates the
       result. It provides simplified, general-purpose access to DACS's access control rule
       evaluation engine, even for programs other than web services, and it lends itself to
       fine-grained access control decisions.

       More specifically, dacscheck checks if a request for object should be granted according to
       specified access control rules and a given evaluation context. To do its job, dacscheck
       needs to know only a few things:

        1. where to find the access control rules to apply;

        2. the name of the object being accessed; and

        3. optionally, an evaluation context that specifies an identity for which access is being
           tested and variables that can be referenced by rules.

       The command does not perform any authentication; it assumes that the caller (or the
       execution environment) has already established the identity for which an access control
       decision is required. It may be used like any other command: run from the command line or
       a shell script, executed by a compiled program, or called from a scripting language such
       as Perl[1], PHP[2].  Python[3], Ruby[4], and Tcl/Tk[5].

       Some simple examples will illustrate how dacscheck can be used.

           Note
           The examples in this document have been simplified for readability; in real use,
           absolute pathnames should appear, error checking should be performed, and so on. Also,
           the dacscheck program and the rules that it requires must have file permissions set
           appropriately.

       The first example shows how a shell script might call dacscheck to test whether the user
       running it is allowed to do so. It obtains the user's identity from the operating system;
       it assumes that the user has invoked the script from the command line and has therefore
       already signed in to the system. In the example, dacscheck obtains the identity through a
       system call, but a script might choose to pass the value of the LOGNAME or USER
       environment variable.

       The shell script simply asks dacscheck if the effective uid (see geteuid(2)[6]) is
       permitted to access /myapp. The exit status of dacscheck ($?) gives the result. The
       pathname /myapp is essentially a label that is used to find the access control rule to
       apply; in this example it simply represents the name of the program. It could be the
       program's filename, but it need not be.

           #! /bin/sh

           dacscheck -q -ieuid -rules /usr/local/myapp/rules /myapp
           st="$?"
           if test "${st}" != 0
           then
             echo "Access is denied"
             exit "${st}"
           fi

           echo "Access is granted"

           # Do some stuff

           exit 0

       The directory /usr/local/myapp/rules might include a file named acl-app.0 that grants
       access only to bob and alice:

           <acl_rule status="enabled">
             <services>
              <service url_pattern="/myapp"/>
             </services>

             <rule order="allow,deny">
              <allow>
                user(":bob") or user(":alice")
              </allow>
             </rule>
           </acl_rule>

           Note
           Access control rules are described in dacs.acls(5)[7]. As with dacs_acs(8)[8], these
           rules must be indexed by dacsacl(1)[9]. For example, in a common use case where a DACS
           configuration file is not being used, the ruleset consulted by dacscheck might be
           indexed using a command like:

               % dacsacl -un -vfs "[acls]file:///users/bobo/my-rules" -vfs "[dacsacls]:file:///dev/null"

           If dacsacl is successful in the example above, a file named INDEX will be created or
           updated in the /users/bobo/my-rules directory, where the files containing the rules
           are also found. Warning messages can usually be ignored provided INDEX looks correct.

       A CGI program can obtain the identity of the user invoking it from the REMOTE_USER
       environment variable and call dacscheck, as demonstrated in the following shell script,
       which uses the same rule as above:

           #! /bin/sh

           if test "${REMOTE_USER}x" = "x"
           then
             idarg=""
           else
             idarg="-i ${REMOTE_USER}"
           fi

           echo "Context-Type: text/plain"
           echo ""

           # Note: append 2>&1 to the end of the next line to capture error messages
           dacscheck -q ${idarg} -rules /usr/local/myapp/rules /myapp

           st="$?"
           if test "${st}" = 0
           then
             echo "Access is granted"
           else
             echo "Access is denied"
           fi

           exit 0

       This example can easily be translated into any scripting language that allows an external
       program to be called and its exit status examined. Here is a similar example in PHP:

           $user = $_SERVER["REMOTE_USER"];
           putenv("REMOTE_USER=$user");
           system("/usr/local/dacs/bin/dacscheck -q -fn DEMO -icgi
                -rules /usr/local/myapp/rules /myapp", $st);
           if ($st != 0) {
           // Access is denied, bail out
             exit($st);
           }

           // Access is granted, proceed

           Note
           Some may question the point of having a program call dacscheck to test if the user
           invoking it is allowed to merely run the program. At first glance it might appear that
           one could achieve the same result by simply setting file permissions such that only
           bob and alice can run the program. If that could be done, the coarse-grained testing
           done by dacscheck in the examples would be unnecessary. It turns out that there is
           more to it than that.

           Setting file permissions to achieve this on a traditional Unix-type system requires
           creating a new group in /etc/group, something that generally can only be done by a
           system administrator. Ordinary users must therefore either bother the system
           administrator each time such a group must be created or modified, or find some other
           way to achieve the same result (e.g., by encryption, using a special setuid or setgid
           command that provides password-protected access, or some other clumsy and possibly
           insecure solution).

           To address this limitation and others, many Unix-type operating systems now include
           file systems that extend the traditional Unix file permissions with an ACL-based
           mechanism (e.g., providing the getfacl(1)[10] and setfacl(1)[11] commands, and the
           acl(3)[12] ACL security API).

           dacscheck provides similar functionality but for arbitrary names, not only for objects
           in the file system, and with respect to arbitrary identities, not only for those known
           to the operating system. For example, a CGI script can call dacscheck to test access
           on behalf of a user known to the web server (e.g., via an account created using
           htpasswd(1)[13]) but not having an account on the underlying system. Therefore,
           besides being portable across platforms and available on systems without ACL-type file
           permissions, dacscheck is a much more general solution than what most operating
           systems provide. In contrast to a system-provided ACL-based mechanism, however,
           dacscheck is not invoked transparently (i.e., it is not called automatically by the
           operating system when a resource such as a file is accessed). Also, with respect to
           testing whether a user is allowed to run a program, that program will typically
           perform the test itself and must therefore begin execution.

           For additional information:

           •   Using FreeBSD's ACLs[14], Dru Lavigne, ONLamp.com[15], 22-Sep-05.

           •   POSIX ACLs in Linux[16], Mike Peters, linux.com[17], 2-Aug-04.

           •   For Solaris, Solaris 10 acl(2)[18], Sun Microsystems[19] and Using Solaris
               ACLs[20] by the Dept. of Computer Science, Duke University[21].

       Because the authorization checking performed by dacscheck is completely separate from that
       performed by the operating system for system calls, a Unix identity such as root has no
       special rights or capabilities as far as dacscheck is concerned unless rules have been
       written to grant them. The same applies to the application of Unix groups.

       The next example demonstrates how some typical Perl code can be improved by dacscheck. The
       code fragment:

           if ($logged_in_as_root || $logged_in_as_current_admin) {
             # Do something privileged...
           }

       which depends on the two variables being properly initialized depending on the value of
       $username, can be replaced by this:

           # Determine if $username has admin privileges
           $output = `dacscheck -q -i $username -app myapp /myapp/admin`;
           $is_admin = ($? >> 8) == 0;

           if ($is_admin) {
             # Do something privileged...
           }

           # Later...
           if ($is_admin) {
             # Do something else privileged...
           }

       The new authorization test depends on the identity that is running the program ($username)
       and the separate ruleset that determines whether that identity should be granted access to
       /myapp/admin, which is simply a label for a rule that might look like this:

           <acl_rule status="enabled">
             <services>
              <service url_pattern="/myapp/admin"/>
             </services>

             <rule order="allow,deny">
              <allow>
                user("%:admin")
              </allow>
            </rule>
           </acl_rule>

       This rule grants access if and only if $username is a member of the DACS group named admin
       or is associated with that DACS role. Membership in that group can be changed dynamically,
       and can even be reduced to zero.

       The important observation is that the conditions that determine whether the user running
       this Perl code has administrative privileges are defined outside of the program and can be
       changed without modifying the code and often without even modifying access control rules.

       A few concepts that are used in this document are described elsewhere. Variables, variable
       namespaces, and expressions that are used in access control rules are discussed in
       dacs.exprs(5)[22]. Naming in DACS is discussed in dacs(1)[23], and DACS groups and roles
       are covered in dacs.groups(5)[24].

           Security
           Clearly dacscheck, its caller, and the resources in question must be "isolated" from
           the user on whose behalf dacscheck is being run, otherwise the user could access the
           resources directly or subvert access control tests. Therefore, dacscheck and its
           caller must either be more privileged than the user on whose behalf it is being run or
           both programs must run in a secure context. This generally means that both dacscheck
           and its caller should be run in isolation from users (as on a remote server) or as an
           effective user ID different from the user's.

   Advantages
       Programs that perform authorization tests typically contain code like:

       •   "If the current user has provided a suitable password, then execute the following
           code, otherwise do not", or

       •   "If the current user is the administrator, do the following", or

       •   "If the current user is allowed to perform an update operation, then show these menu
           items, otherwise do not show them"

       Complicated applications can be littered with these kinds of tests, making them prone to
       bugs and security problems. Changes to security policies may involve modifications
       throughout an application or suite of applications. Also, password handling is often
       incorporated into such programs; because password management can require a significant
       implementation effort and is difficult to do securely, it seems wise to try to leverage
       existing implementations.

       Compared to custom-coded solutions, dacscheck has many advantages:

       Data-driven policies
           As opposed to specially-written access control logic, data-driven (rule-based)
           functionality is superior because:

           •   Access control rules are separate from code, so changes to a set of rules
               automatically applies to all uses of those rules throughout an application or set
               of applications; code does not need to be modified if the policy is changed.

           •   Bug fixes and improvements to rules are automatically available to programs that
               use dacscheck; no recompilation of applications is necessary.

           •   The person who administers the rules does not have to be the application's
               programmer (or even someone who understands the code), so delegating
               responsibility is much easier. This reduces the amount of programming required
               when changes are required, reduces code maintenance effort, and decreases the
               chance of error.

           •   It is usually easier to understand (and express) a set of rules that describes an
               access control policy; code that implements the same policy will be more complex
               and difficult to understand, increasing the chance of error.

       Programming Efficiency

           •   Applications are simplified and programming time and effort are reduced because
               existing access control code (i.e., dacscheck) is reused.

           •   Sophisticated rules can be constructed without having to write any code.  DACS
               features are available, such as roles and groups, and can be used to construct
               simpler and more expressive authorization policies than are likely to be
               hand-coded.

       Portability
           Rules are platform independent, can be stored remotely from the applications that use
           them, and can potentially be evaluated remotely.  dacscheck is available for a variety
           of platforms.

       Increased Sharing
           Rules can be shared and used in different situations and by different programs.

       Flexibility

           •   Because it does not rely on a web server, it can be used by virtually any
               CGI-based program.

           •   With respect to DACS, it can be used in circumstances where the mod_auth_dacs[25]
               module cannot be used with Apache, or where Apache cannot be used at all.

           •   Because it is implemented as an ordinary command, dacscheck can be used from the
               command line or invoked from almost any script or program.

           •   For CGI-based programs, dacscheck can be used without any assistance from a system
               administrator; e.g., it does not require a web server to be configured to provide
               authorization for a CGI program because all access control functionality is
               performed within the program.

       Increased Security
           dacscheck neither performs authentication nor relies on any particular authentication
           method, so the authentication method can be changed without affecting the
           application's use of dacscheck. Any supported means of authentication can be used, not
           only the typical password-based method.

       While the performance of dacscheck ought not to be a factor for many applications, the
       C/C++ API can be used where it is an issue. This API can be used to incorporate dacscheck
       functionality into compiled programs and extensible languages, such as Perl, Python,
       Tcl/Tk, and PHP.

   Identities
       The identity for which access is to be tested is given to the program or obtained by the
       program from its execution environment. This identity is converted into DACS's internal
       representation.

       More than one identity can be specified; the check is made on behalf of the union of all
       the identities. If the identities bob and alice are specified, for instance, a rule that
       is satisfied by either identity may grant access.

       If no identity is given, the check is made on behalf of an unauthenticated user.

       An identity can be:

       •   a login name that dacscheck maps to from the real or effective uid of the program
           (i.e., the user who is running the program);

       •   a DACS user identity (e.g., :carol, DSS:bob, or EXAMPLE-COM::DEMO:alice, see
           dacs(1)[26]);

       •   a simple name (bob is equivalent to :bob); or

       •   a name expressed in the concise syntax[27], which gives a username and, optionally,
           roles and attributes for the identity. Any identity that has expired is not used.

           Notesdacscheck validates the syntax of an identity it is given, converts and expands it
               to the concise syntax if necessary, and then converts it into its internal
               representation for credentials. These credentials are destroyed when the program
               terminates.

               Regardless of how it is specified, each identity must satisfy the syntactic
               requirements of a DACS user identity after this conversion and expansion (see
               dacs(1)[26]). If a login name is specified as an identity, for example, it must be
               valid as a component of a DACS user identity; therefore, it cannot contain any
               invalid characters.

           •   If no IP address is provided for an identity, it is obtained from the REMOTE_ADDR
               environment variable when available, otherwise a default of 127.0.0.1 is used. The
               IP address associated with credentials is tested using the user() predicate.

           •   If an identity that is being tested includes a federation name, since the default
               federation name is unlikely to be correct, it will probably be necessary to tell
               dacscheck which federation name to compare against using the -fn flag.

       Here are some examples of identities that may follow the -i flag:

           bob
           :bob
           DSS:bob
           {u = bob}
           {u="bob"}
           {u="alice",g="admin"}
           {u="DSS:bob",g="guest"}
           {u="bob",a="a", g="guest"}

           Note
           This string may need to be quoted appropriately on the command line because the brace
           characters are significant to some shells; e.g.,

               -i '{u="bob"}'

       Apache and other web servers set the environment variable REMOTE_USER to the authenticated
       identity that invoked a web service. Provided its syntax is suitable, this identity can be
       passed to dacscheck. For DACS-wrapped web services, DACS identities are available in this
       variable.

       By default, the federation, jurisdiction, and hostnames associated with the rules are
       derived from the system's hostname as returned by gethostname(3)[28]. If that name is
       unsuitable because it is not a FQDN (i.e., it is not a fully-qualified domain name because
       it does not contain a period), each of the alias names is examined (using
       gethostbyname(3)[29]) until a FQDN is found. The jurisdiction name comes from the
       left-most component of the selected FQDN and the federation domain and name come from the
       remaining components. If no FQDN is found, the system's hostname will be selected as the
       jurisdiction name and defaults will be used as the federation domain and name (EXAMPLE.COM
       and EXAMPLE-COM, respectively).

       If the system's hostname is found to be (or explicitly given as) demo.example.com, for
       instance, the following variables will be set as indicated during rule evaluation:

       •   ${Conf::FEDERATION_NAME} and ${DACS::FEDERATION} are both set to EXAMPLE-COM (dots are
           mapped to dashes to form a valid name)

       •   ${Conf::FEDERATION_DOMAIN} is set to EXAMPLE.COM

       •   ${Conf::JURISDICTION_NAME} and ${DACS::JURISDICTION} are set to the jurisdiction name,
           DEMO

       •   ${DACS::HTTP_HOST} is set to demo.example.com:80

       Often, rules and identities can be expressed such that the names chosen for the federation
       and jurisdiction are unimportant. When this is not the case, however, and the defaults
       chosen by dacscheck are incorrect, they can be set on the command line. In some
       circumstances it might be appropriate for the jurisdiction name to be the name of the
       application, for example.

       Regardless of their origins, federation and jurisdiction names must always be
       syntactically valid (see dacs(1)[26]).

   Objects
       While an object will often be an actual thing, such as a file, menu, or variable, it can
       also be an abstraction, such as an operation.  dacscheck works with names - in the form of
       URIs - rather than objects per se.  It does not associate any particular meaning with
       names, it merely uses them to locate an applicable access control rule. Therefore,
       provided the rule writer and applications that consult the rules agree on the naming
       scheme, the names that are chosen are largely irrelevant.

       An application assigns names to every object or class of objects that need to be
       referenced by access control rules. At its simplest, only one name is required (the name
       of the application, for example). In more complex situations, a wide variety of objects
       need to be named. The choice of names and the details of the naming hierarchy are up to
       the particular application, much like the organization of a software package's run-time
       file and directory organization depends on the particular package.

       The object argument is the name that is matched against the services specified in access
       control rules. It can be either a URI or an absolute pathname (one that begins with a
       slash character), and either can have an optional query string component attached. An
       absolute pathname path is mapped internally to a URI as file://path; e.g., /myapp is
       interpreted as file:///myapp (see RFC 1738[30]).

       The various components of the URI that names the object are available as DACS variables
       and environment variables (see below). If a query string is given, it is parsed and the
       individual arguments are made available to rules through the Args namespace, just as for
       DACS-wrapped web services.

           Note
           Only the path component of the URI is considered when DACS matches an object's name
           against the url_pattern of an access control rule. At present, the object name is not
           automatically canonicalized or resolved (see RFC 3986[31]), as is usually done by a
           web server, so relative path components such as "." and ".." should be avoided.

   Rule Evaluation Context
       Rules are evaluated within an execution context that may affect expression evaluation
       implicitly or may be examined explicitly through variables.

       Since dacscheck does not consult the DACS configuration files, the Conf namespace is
       instantiated with few variables. At present, only the VFS directives are available in it.

       The Args namespace is instantiated if an object argument has a query string component.

       The DACS namespace is instantiated with a few standard variables (such as
       ${DACS::JURISDICTION}) but can also be instantiated in various ways from the command line
       and from files.

       The Env namespace is instantiated from the environment. Syntactically invalid variable
       names are silently ignored.

       Many variables normally set by a web server are instantiated by dacscheck based on the
       object name. These variables are available in the Env and DACS namespaces. For example, if
       the object name is https://example.com:8443/myapp/edit-menu?entry=item1, the following
       variables will be set as indicated:

           ${Env::HTTPS}=on
           ${Env::SERVER_NAME}=example.com
           ${Env::SERVER_ADDR}=142.179.101.118
           ${Env::HTTP_HOST}=example.com:8443
           ${Env::SERVER_PORT}=8443
           ${Env::REQUEST_URI}=/myapp/edit-menu
           ${Env::DOCUMENT_ROOT}=/
           ${Env::REQUEST_METHOD}=GET
           ${Env::SERVER_SOFTWARE}=dacscheck-1.4.8b
           ${Env::QUERY_STRING}=entry=item1
           ${Env::ARG_COUNT}=1
           ${Env::CURRENT_URI}=/myapp/edit-menu?entry=item1
           ${Env::CURRENT_URI_NO_QUERY}=/myapp/edit-menu

       Variables of the same name will also be set in the DACS namespace and exported as
       environment variables. The value of ${Args::entry} will be item1. The request method
       defaults to GET. The variable ${Env::REMOTE_USER} (and therefore ${DACS::REMOTE_USER} and
       the environment variable REMOTE_USER) will be set based on the first identity specified on
       the command line; if no identity has been specified, this variable will be undefined.

   An Example Application
       To illustrate how the pieces fit together, let's consider a hypothetical (yet realistic)
       calendar application named cal that is written in Perl and invoked as a CGI program. We'll
       allow a user that has been authenticated by the web server to read, create, or update only
       her own calendars, unless the owner of a calendar gives her permission to perform a read
       or update operation on the calendar. Each owner can specify which users have access to her
       own calendar and the type(s) of access allowed.

       This authorization policy can be specified fairly easily. One approach is to use:

       •   A main rule that delegates responsibility for specifying a security policy for each
           user's calendars to that user.

       •   Per-user, per-calendar rules that say which users can access a calendar and in what
           way or ways.

       The program's administrator might collect all of the run-time files for the application in
       the directory /usr/local/cal and its subdirectories, and organize it as follows:

       /usr/local/cal/rules/{acl-rule.0,acl-rule.1,...}
           General rules for the application

       /usr/local/cal/users/username
           Root directory for calendars owned by username

       /usr/local/cal/users/username/cal-1/data/*
           Per-calendar data files

       /usr/local/cal/users/username/rules/{acl-cal1.0,acl-cal2.0,...}
           Per-calendar DACS access control files

       /usr/local/cal/users/username/groups/*
           Per-user DACS group lists, one per file

       Given these naming conventions:

       •   to test whether it should perform a particular operation, the application would call
           dacscheck, telling it to use the rules it finds in /usr/local/cal/rules.

       •   the general rules for the application would delegate access control decisions for
           objects with names that match /users/username/* to access control rules found in the
           directory /usr/local/cal/users/username/rules. These rules would describe which users,
           if any, would be permitted to perform a given operation on the calendar.

       •   the application would use object names of the form /users/username/cal-1?OP=operation
           as arguments to dacscheck. The ruleset for cal-1 would determine whether a given
           identity is allowed to perform the requested operation on the calendar. For example,
           alice (the owner) might be granted access regardless of the value of the OP argument,
           while bob might be granted access only if OP=read, and all others might be denied
           access. Later, alice might define a set of users that she names family and change the
           rule to allow any member of that group read and update access.

       Users' access control rules could themselves be under access control. A command line, GUI,
       or web interface would give the administrator and users the ability to manage rules.

       See the EXAMPLES[32] section for example rules.

       This is by no means the only way to organize the calendars, and a delegation-based
       approach isn't required. The administrator might instead put all of the rules under a
       common directory, like /usr/local/cal/rules/acl-username.0/{acl-cal1.0,acl-cal2.0,...}, or
       put them closer to the calendar they are controlling, like
       /usr/local/cal/users/username/cal-1/acl-cal1.0.

       Instead of testing whether an operation is permitted, rules can be written to return a
       constraint string that tells the caller what kind (or kinds) of access are permitted. The
       program's output line will include the constraint string within quotes.

   Comparing dacscheck with dacs_acs
       dacs_acs(8)[8] is the DACS component that is called by Apache (by the
       DACSmod_auth_dacs[25] module, actually) to perform access control processing on web
       service requests. Its operation is normally invisible to web services; dacs_acs does all
       of its work before a web service is even executed or a web page is returned.

       dacscheck performs a function similar to the -check_only mode of operation of dacs_acs in
       that it simply returns an access control decision. There are important differences between
       the two programs, however.

       dacscheck:

       •   is not a CGI program (though it can be called from one);

       •   does not require mod_auth_dacs[25];

       •   does not use any DACS configuration files;

       •   does not directly interact with a web server or any other DACS programs; and

       •   runs at the privilege level of the user invoking it rather than the privilege level of
           Apache.

       While dacscheck uses ordinary DACS access control rules (dacs.acls(5)[7]), unlike most
       DACS commands it does not consult any DACS configuration files. The evaluation environment
       for access control rules is similar to that of web service testing, but it is not
       identical since there need not be a web server in the picture. Other than the attributes
       related to constraints, attributes such as pass_credentials have no meaning to dacscheck.

       Use and configuration of DACS by dacscheck is greatly simplified because no real
       federation or jurisdictions are defined; a completely self-contained environment is
       created so that a single program or set of related programs can perform both
       course-grained and fine-grained access control tests. No federation or jurisdiction
       cryptographic keys are used, and no real DACS credentials are created. Federation and
       jurisdiction names are instantiated, but those who write rules will often not need to be
       aware of them.

OPTIONS

       The arguments are processed as they are examined (left-to-right) and their ordering can be
       significant; for example, values established by the -fh flag may affect options that
       follow it, such as those that use string interpolation. Exactly one object argument is
       required.

       -admin
           All identities that follow on the command line are DACS identities that satisfy the
           dacs_admin() function. Refer to the ADMIN_IDENTITY configuration directive in
           dacs.conf(5)[33] and the "a" attribute for identities.

       -app appname
           Specify an application name to be used to construct default paths (see the -rules and
           -groups flags).

       -context file
           Variable definitions for the DACS namespace are read, one per line, in the format
           name=value (with optional quotes around the value). The name must be syntactically
           valid. If file is -, the standard input is read. For example, if file contains the two
           lines:

               FOO=one
               BAZ=two

           then within access control rules ${DACS::FOO} will have the value "one" and
           ${DACS::BAZ} will have the value "two". This flag may be repeated, although the
           standard input can be read only once.

       -Dname=value
           This is equivalent to -varname=value.

       -dump
           Perform all initializations, display the evaluation context, and then exit.

       -F field_sep
           When roles are looked up, use the character field_sep as the field separator character
           instead of the default. For details, refer to the description of the VFS directive in
           dacs.conf(5)[34].

               Note
               Note that only the first occurrence of the character (from left to right) is
               treated as the separator character.

       -fd domain
           Use domain as the domain name for the federation. It must be syntactically valid.

       -fh hostname
           Use hostname, a fully-qualified domain name, as the system's hostname and to derive
           the federation and jurisdiction names. It must be syntactically valid.

       -fj jurname
           Use jurname as the jurisdiction name. It must be syntactically valid.

       -fn fedname
           Use fedname as the federation name. It must be syntactically valid.

       -groups group_vfs
           By default, dacscheck expects to find DACS group definitions rooted in the directory
           dacscheck/groups relative to DACS_HOME (e.g., /usr/local/dacs/dacscheck/groups), or if
           -app appname is given, rooted in the directory dacscheck/appname/groups relative to
           DACS_HOME (e.g., /usr/local/dacs/dacscheck/myapp/groups) This flag specifies a
           different location. It can be an absolute pathname (which will be string interpolated
           - see dacs.conf(5)[35]) or a URI in the syntax of the VFS[34] configuration directive.
           Examples:

               -groups "[groups]dacs-fs:/local/groups"
               -groups /home/bob/mygroups

           By default, a reference to the group %FOO:people will be mapped to a file named
           people.grp within the directory FOO relative to the DACS group directory.

       -h
           Prints the usage blurb.

       -i ident
           The given identity is added to the set of identities in effect during checking. This
           identity does not necessarily have an account on the system. If ident is the empty
           string, however, the flag has no effect; this is convenient behaviour when the flag is
           used like -i ${Env::REMOTE_USER:-""}, for example, where REMOTE_USER may not have been
           set.

       -icgi
           If the environment variable REMOTE_USER is set to a valid simple name or DACS
           identity, it is added to the set of identities in effect during checking. If the
           variable is not set or is invalid, this flag has no effect.

       -icgig
           Like the -icgi flag, except any roles associated with the username will be added.

       -il ident
           The given identity is "local" and must correspond to an account on the system; if the
           -groups flag is in effect, the account's group membership will be added as roles to
           ident.

       -ilg ident
           Like the -ilg flag, except the account's group membership will be added as roles to
           ident regardless of whether the -groups flag is in effect.

       -ieuid
           The effective uid of the program is added to the set of identities. If the -groups
           flag is in effect, the account's group membership will be added as roles to ident.

       -ieuidg
           The effective uid of the program is added to the set of identities. The account's
           group membership will be added as roles to ident regardless of whether the -groups
           flag is in effect.

       -iuid
           The real uid of the program is added to the set of identities. If the -groups flag is
           in effect, the account's group membership will be added as roles to ident.

       -iuidg
           The real uid of the program is added to the set of identities. The account's group
           membership will be added as roles to ident regardless of whether the -groups flag is
           in effect.

       -lg
           For each local identity that follows on the command line, use its Unix group
           membership to the identity's roles.

       -ll log_level
           Set the debugging output level to log_level (see dacs(1)[23]). The default level is
           warn, and the -v flag bumps the level to debug or trace.

       -name_compare method
           Exactly like the NAME_COMPARE[36] directive, set the default method used to compare
           DACS names in various contexts to method, which may be (case-insensitively) case,
           nocase, or default.

       -q
           Be quiet, except for error messages; the outcome will not be printed to stdout. The -v
           and -ll flags are independent of this.

       -redirect
           If access is denied and the applicable rule calls redirect()[37] with the
           BY_SIMPLE_REDIRECT argument, then the specified URL is printed to stdout. This flag
           enables the -q flag.

       -roles roles_vfs
           Roles for each identity that follows on the command line will be looked up using
           roles_vfs. It can be an absolute pathname (which will be string interpolated - see
           dacs.conf(5)[35]) or a URI in the syntax of the VFS[34] configuration directive. If
           any roles are found, they will be added to any other roles specified for the user
           (whether explicitly listed or obtained from Unix group membership). For example, if
           /usr/local/myapp/roles contains:

               bobo:users
               auggie:admin,users
               harley:guest

           then the command line:

               % dacscheck -roles /usr/local/myapp/roles -i auggie /myapp/admin

           will test access for the identity {u="auggie",g="admin,users"}.

       -rules rule_vfs
           By default, dacscheck expects to use a ruleset rooted in the directory dacscheck/acls
           relative to DACS_HOME (e.g., /usr/local/dacs/dacscheck/acls), or if the flag -app
           appname is given, rooted in the directory dacscheck/appname/acls relative to DACS_HOME
           (e.g., /usr/local/dacs/dacscheck/myapp/acls). This flag specifies a different ruleset
           to be used. It can be an absolute pathname (which will be string interpolated - see
           dacs.conf(5)[35]) or a URI in the syntax of the VFS[34] configuration directive.
           Examples:

               -rules "[acls1]dacs-fs:/local/acls"
               -rules /usr/local/myrules

           This flag may be repeated; rulesets will examined in the order in which they are
           specified on the command line.

       -v
           Increase the level of debugging output. The flag may be repeated.

       -var name=value
           Like the -context flag, this adds a variable definition to the DACS namespace. The
           variable DACS::name will be assigned the string value. The name must be syntactically
           valid. This flag may be repeated.

       -vfs vfs_uri
           Add vfs_uri as a VFS[34] configuration directive. This flag may be repeated, with
           later occurrences having a higher "priority" than earlier ones (just as if they
           appeared later in dacs.conf; see dacs.conf(5)[33]).

       --
           This marks the end of the flag arguments.

EXAMPLES

       To illustrate how dacscheck might be used with real applications, here are some examples.
       The first few continue with the hypothetical calendar application described earlier.

        1. The file /usr/local/cal/rules/acl-rule.0 might look like:

               <acl_rule status="enabled">
                <services>
                 <delegate url_pattern="/users/alice/*"
                         rule_uri="/usr/local/cal/users/alice/rules/>
                 <delegate url_pattern="/users/bob/*"
                         rule_uri="/usr/local/cal/users/bob/rules/>
                 <service url_pattern="/usr/local/cal/bin/*"/>
                </services>

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

           This rule redirects requests for a particular user's calendar to that user's access
           control rules. It also says that access to the application's binaries is restricted to
           authenticated users. The application might issue a command such as:

               % dacscheck -i $REMOTE_USER -rules /usr/local/cal/rules object

           which will return an exit status of 0 if REMOTE_USER is granted access to object;
           otherwise an exit status of 1 will be returned. A better choice is to use the command:

               % dacscheck -icgi -rules /usr/local/cal/rules object

           which will leave the user unauthenticated if REMOTE_USER is unset or invalid.

        2. The file /usr/local/cal/users/alice/rules/acl-cal1.0 contains the rule for user
           alice's "Calendar 1" and might look like:

               <acl_rule status="enabled">
                <services>
                 <service url_pattern="/users/alice/cal-1/*"/>
                </services>

                <rule order="allow,deny">
                  <precondition>
                    <predicate> user(":alice") </predicate>
                  </precondition>
                  <allow>
                    return(1)
                  </allow>
                </rule>

                <rule order="allow,deny">
                  <precondition>
                    <predicate> ${Args::OP} eq "read" </predicate>
                  </precondition>
                  <allow>
                    user(":bob")
                  </allow>
                </rule>

               </acl_rule>

           This rule says that alice is allowed full access to the calendar (there is no
           restriction on the operation), but bob only has read access.  dacscheck would be
           called with /users/alice/cal-1?OP=create, /users/alice/cal-1?OP=update, or
           /users/alice/cal-1?OP=read to test for authorization to perform a create, update, or
           read operation on the calendar, respectively.

        3. If alice defines a DACS group that she calls family and adds the names julia and
           auggie to that group, she might modify the rule above by adding the following:

               <rule order="allow,deny">
                  <precondition>
                    <predicate> ${Args::OP} eq "read"
                            or ${Args::OP} eq "update"</predicate>
                  </precondition>
                  <allow>
                    user("%:alice-family")
                  </allow>
                </rule>

           This rule says that any member of the group alice-family is allowed read and update
           access to this calendar. The command:

               % dacscheck -i julia /users/alice/cal-1?OP=update

           would report that access is granted.

        4. The membership of alice's group called alice-family might be specified in the file
           /usr/local/cal/users/alice/groups/family

               <acl_rule status="enabled">
                <services>
                 <service url_pattern="/users/alice/groups/*"/>
                </services>

                <rule order="allow,deny">
                  <precondition>
                    <predicate> user(":alice") </predicate>
                  </precondition>
                  <allow>
                    return(1)
                  </allow>
                </rule>
               </acl_rule>

           This rule allows only alice to manage the membership of this group, but she is free
           modify the rule to allow others to manage her groups.

        5. As a final example for this application, alice's rules might also be under access
           control:

               <acl_rule status="enabled">
                <services>
                 <service url_pattern="/users/alice/groups/*"/>
                </services>

                <rule order="allow,deny">
                  <precondition>
                    <predicate> user(":alice") </predicate>
                  </precondition>
                  <allow>
                    return(1)
                  </allow>
                </rule>
               </acl_rule>

           This rule allows only alice to manage the membership of this group, but she is free
           modify the rule to allow others to manage her groups.

        6. A popular open source web log analyzer program, written in Perl, can be invoked as a
           CGI program. The program includes security provisions whereby it can restrict access
           to any user authenticated by the web server, by username (using REMOTE_USER, as
           exported by the web server), or based on the user's IP address (using REMOTE_ADDR).
           The approximately 40 lines of code (plus assorted initializations) that implements
           this security policy can essentially be replaced by just a few lines of code:

               my $exit_value = 0;
               system "/usr/local/dacs/bin/dacscheck", "-q", "-icgi", "-rules",
                  "/usr/local/webstats/acls", "/webstats";
               $exit_value  = $? >> 8;
               # print "dacscheck returned $exit_value for user \"$remote_user\"\n";
               if ($exit_value != 0) {
                 # dacscheck denies access; print message and exit
                 exit 1;
               }

               # dacscheck grants access, so continue

               Tip
               The DACS distribution includes a Perl module
               (/usr/local/dacs/lib/perl/DACScheck.pm) to make dacscheck a little easier to use.
               The example above would be written as:

                   use DACScheck.pm;
                   dacscheck_rules("/usr/local/webstats/acls");

                   my $result = dacscheck_cgi("/webstats");
                   if ($result != 1) {
                     # dacscheck denies access; print message and exit
                     exit 1;
                   }

                   # dacscheck grants access, so continue

           A simple DACS access control rule can be written to duplicate the program's security
           functionality (using the user() and from() predicates, see dacs.exprs(5)[22]), but
           more sophisticated policies can be added easily, all without having to modify the Perl
           program again.

DIAGNOSTICS

       The program exits 0 if access is granted and 1 if access is denied. Any other exit status
       indicates an error occurred.

BUGS

       A lightweight method of defining DACS groups is needed. Once the internal are stable, this
       program's functionality will be made available through a C/C++ API, which will permit
       direct, efficient use by other applications and extensible languages (through perlxs(1),
       for example).

       The DACS_ACS argument[38] is not recognized by dacscheck.

       Identities are not considered when roles are looked up; only the username is matched.

       Unlike dacs_acs(8)[8], there is no support for automatically setting variables by parsing
       a message body (a MIME document).

       It might be possible to create a layer between an application and the underlying system so
       that dacscheck can be called transparently, or nearly so.

SEE ALSO

       See dacs(1)[23], dacsacl(1)[9], dacs.acls(5)[7], dacs.conf(5)[33], dacs.exprs(5)[22],
       dacs.groups(5)[24], dacs.java(7)[39].

       Rule-based access control[40]

       DACScheck.pm

AUTHOR

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

COPYING

       Copyright2003-2013 Distributed Systems Software. See the LICENSE[42] file that accompanies
       the distribution for licensing information.

NOTES

        1. Perl
           http://www.perl.org/

        2. PHP
           http://www.php.net/

        3. Python
           http://www.python.org

        4. Ruby
           http://www.ruby-lang.org

        5. Tcl/Tk
           http://www.tcl.tk/software/

        6. geteuid(2)
           http://www.freebsd.org/cgi/man.cgi?query=geteuid&apropos=0&sektion=2&manpath=FreeBSD+9.1-RELEASE&format=html

        7. dacs.acls(5)
           http://dacs.dss.ca/man/dacs.acls.5.html

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

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

       10. getfacl(1)
           http://www.freebsd.org/cgi/man.cgi?query=getfacl&apropos=0&sektion=1&manpath=FreeBSD+9.1-RELEASE&format=html

       11. setfacl(1)
           http://www.freebsd.org/cgi/man.cgi?query=setfacl&apropos=0&sektion=1&manpath=FreeBSD+9.1-RELEASE&format=html

       12. acl(3)
           http://www.freebsd.org/cgi/man.cgi?query=acl&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE&format=html

       13. htpasswd(1)
           http://httpd.apache.org/docs/2.2/programs/htpasswd.html

       14. Using FreeBSD's ACLs
           http://www.onlamp.com/pub/a/bsd/2005/09/22/FreeBSD_Basics.html

       15. ONLamp.com
           http://www.onlamp.com

       16. POSIX ACLs in Linux
           http://www.cs.unc.edu/cgi-bin/howto?howto=linux-posix-acls

       17. linux.com
           http://linux.com

       18. Solaris 10 acl(2)
           http://docs.sun.com/app/docs/doc/816-5167/6mbb2jaf2?a=view

       19. Sun Microsystems
           http://www.sun.com

       20. Using Solaris ACLs
           http://www.cs.duke.edu/csl/faqs/solaris-acls.php

       21. Dept. of Computer Science, Duke University
           http://www.cs.duke.edu

       22. dacs.exprs(5)
           http://dacs.dss.ca/man/dacs.exprs.5.html

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

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

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

       26. dacs(1)
           http://dacs.dss.ca/man/dacs.1.html#naming

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

       28. gethostname(3)
           http://www.freebsd.org/cgi/man.cgi?query=gethostname&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE&format=html

       29. gethostbyname(3)
           http://www.freebsd.org/cgi/man.cgi?query=gethostbyname&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE&format=html

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

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

       32. EXAMPLES
           http://dacs.dss.ca/man/#EXAMPLES

       33. dacs.conf(5)
           http://dacs.dss.ca/man/dacs.conf.5.html

       34. dacs.conf(5)
           http://dacs.dss.ca/man/dacs.conf.5.html#VFS

       35. dacs.conf(5)
           http://dacs.dss.ca/man/dacs.conf.5.html#interpolation

       36. NAME_COMPARE
           http://dacs.dss.ca/man/dacs.conf.5.html#NAME_COMPARE

       37. redirect()
           http://dacs.dss.ca/man/dacs.exprs.5.html#redirect

       38. DACS_ACS argument
           http://dacs.dss.ca/man/dacs_acs.8.html#dacs_acs_argument

       39. dacs.java(7)
           http://dacs.dss.ca/man/dacs.java.7.html

       40. Rule-based access control
           http://www-128.ibm.com/developerworks/webservices/library/ws-soa-access.html

       41. www.dss.ca
           http://www.dss.ca

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