<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!-- references -->
<!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC2629 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2629.xml">
<!ENTITY RFC3552 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3552.xml">
<!ENTITY I-D.narten-iana-considerations-rfc2434bis SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.narten-iana-considerations-rfc2434bis.xml">
]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<!-- For a complete list and description of processing instructions (PIs), 
     please see http://xml.resource.org/authoring/README.html. -->
<!-- Below are generally applicable Processing Instructions (PIs) that most I-Ds might want to use.
     (Here they are set differently than their defaults in xml2rfc v1.32) -->
<?rfc strict="yes" ?>
<!-- give errors regarding ID-nits and DTD validation -->
<!-- control the table of contents (ToC) -->
<?rfc toc="no"?>
<!-- generate a ToC -->
<?rfc tocdepth="4"?>
<!-- the number of levels of subsections in ToC. default: 3 -->
<!-- control references -->
<?rfc symrefs="yes"?>
<!-- use symbolic references tags, i.e, [RFC2119] instead of [1] -->
<?rfc sortrefs="yes" ?>
<!-- sort the reference entries alphabetically -->
<!-- control vertical white space 
     (using these PIs as follows is recommended by the RFC Editor) -->
<?rfc compact="yes" ?>
<!-- do not start each main section on a new page -->
<?rfc subcompact="no" ?>
<!-- keep one blank line between list items -->
<!-- end of list of popular I-D processing instructions -->
<rfc category="exp" docName="draft-deason-afs3-acl-restrictions-01" ipr="trust200902">
  <!-- category values: std, bcp, info, exp, and historic
     ipr values: full3667, noModification3667, noDerivatives3667
     you can add the attributes updates="NNNN" and obsoletes="NNNN" 
     they will automatically be output with "(if approved)" -->

  <!-- ***** FRONT MATTER ***** -->

  <front>
    <!-- The abbreviated title is used in the page header - it is only necessary if the 
         full title is longer than 39 characters -->

    <title abbrev="AFS3 ACL Restrictions">Methods of Specifying Restrictions on AFS3 ACLs</title>

    <author fullname="Andrew Deason" initials="A.P.D." surname="Deason">
      <organization abbrev="Sine Nomine">Sine Nomine Associates</organization>

      <address>
        <postal>
          <street>43596 Blacksmith Square</street>
          <city>Ashburn</city>
          <region>Virginia</region>
          <code>20147-4606</code>
          <country>USA</country>
        </postal>

        <phone>+1 703 723 6673</phone>

        <email>adeason@sinenomine.net</email>

        <!-- uri and facsimile elements may also be added -->
      </address>
    </author>

    <author fullname="Michael Meffie" initials="M.M." surname="Meffie">
      <organization abbrev="Sine Nomine">Sine Nomine Associates</organization>

      <address>
        <postal>
          <street>43596 Blacksmith Square</street>
          <city>Ashburn</city>
          <region>Virginia</region>
          <code>20147-4606</code>
          <country>USA</country>
        </postal>

        <phone>+1 703 723 6673</phone>

        <email>mmeffie@sinenomine.net</email>

        <!-- uri and facsimile elements may also be added -->
      </address>
    </author>

    <author fullname="Thomas Keiser" initials="T.E.K." surname="Keiser">
      <organization abbrev="Sine Nomine">Sine Nomine Associates</organization>

      <address>
        <postal>
          <street>43596 Blacksmith Square</street>
          <city>Ashburn</city>
          <region>Virginia</region>
          <code>20147-4606</code>
          <country>USA</country>
        </postal>

        <phone>+1 703 723 6673</phone>

        <email>tkeiser@sinenomine.net</email>

        <!-- uri and facsimile elements may also be added -->
      </address>
    </author>

    <date year="2010" />

    <!-- If the month and year are both specified and are the current ones, xml2rfc will fill 
         in the current day for you. If only the current year is specified, xml2rfc will fill 
	 in the current day and month for you. If the year is not the current one, it is 
	 necessary to specify at least a month (xml2rfc assumes day="1" if not specified for the 
	 purpose of calculating the expiry date).  With drafts it is normally sufficient to 
	 specify just the year. -->

    <!-- Meta-data Declarations -->

    <area>General</area>

    <workgroup>N/A</workgroup>

    <!-- WG name at the upperleft corner of the doc,
         IETF is fine for individual submissions.  
	 If this element is not present, the default is "Network Working Group",
         which is used by the RFC Editor as a nod to the history of the IETF. -->

    <keyword>afs3</keyword>
    <keyword>acl</keyword>

    <!-- Keywords will be incorporated into HTML output
         files in a meta tag but they have no effect on text or nroff
         output. If you submit your draft to the RFC Editor, the
         keywords will be used for the search engine. -->

    <abstract>

      <t>
        The AFS-3 ACL 'a' bit gives users unfettered power to grant, or 
        revoke, privileges, with no provision for enforcing site policy.  This memo
        provides several alternative mechanisms for creating restrictions on what
        powers the 'a' bit denotes.  Three alternative mechanisms for restricting the
        power of the 'a' bit are proposed:
   
        a method for overlaying the ACL with a site-controlled ACL;
   
        a method for masking the ACL with a site-controlled privilege mask;

        and a finely granular meta-acl mechanism for restricting to whom
        privileges may be delegated, and which privileges may be given to different
        classes of principals.
   
        This memo will serve as a basis for the ACL restriction discussion with the
        AFS-3 protocol working group.  The intended goal of this discussion is to
        reach consensus on standardization of one or more solutions, and then publish
        a BCP status memo.
      </t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">
<t>Currently sites may give users administrative rights on certain
directories in AFS, such as home directories and shared project
directories.  Users should not, but can, give overly permissive ACLs to
those directories. For example, a user could give write and even admin
permissions to the system:anyuser group
('fs sa $HOME system:anyuser rlidwka').</t>

<t>This can which can lead to problematic situations, especially for
directories that can be served over http. As it stands today, the only
possible way for AFS administrators to prevent this (at least in
OpenAFS) is to monitor the fileserver's audit log, and correct ACLs that
are overly permissive. But this is suboptimal, and is an after-the-fact
check.</t>

<t>If you see a viable solution to this problem not listed here, or see any
problems with our methods, please let us know. Or if a solution to this
problem is valuable to you or your organization, also please let us
know.</t>

<section title="Requirements Language">

<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document
are to be interpreted as described in <xref target="RFC2119">RFC
2119</xref>.</t>

</section>

</section>

<section title="Proposed solutions">

<t>Discussions have shown that preventing this is not a simple issue, and
that there are a few ways to go about it, each with advantages and
disadvantages. Here we will outline 3 general approaches, and show how
to use them to meet certain illustrative use cases.</t>

<t>Since the rest of this is quite long, here's a quick summary of the
conclusions. We have three methods: 'method A' is the "volume-level
ACL overlays" idea, 'method B' is the "volume ACL masks" idea, and
'method C' is the "volume ACL policies" idea. While none of these in
themselves cover all corners of all possible use cases, we would
probably implement either C by itself, or A and B together to cover a
large enough majority of use cases. Of course, unless a serious
problem is found, there is no reason to not implement all three.</t>

<t>The bottom line is that I find method C to be the most flexible and
the least confusing to end-users, but it is the most confusing to
administrators, and it is the slowest (when changing the volume-level
permissions). Using methods A+B has the opposite pros/cons.</t>

<t>Here are the details. Each method has an explanation for what it
generally is and how it works, followed by its use in a few simple
use-case scenarios, followed by the pros/cons.</t>

<section title="Method A: volume-level ACL overlays">

<t>With this method, we maintain a single additional ACL in the volume
metadata, which is applied to access checks in the volume after
performing the per-directory ACL check. It can be thought of as
similar to the OpenAFS fileserver's -implicit flag, but more
generalized.</t>

<t>For example, if we wanted a volume where system:backups was guaranteed
to have 'rl' rights, and system:evilusers was guaranteed to not have
_any_ rights, the volume-level ACL overlay would look like this:</t>

<figure align="center">
<artwork align="left"><![CDATA[

positive:
 system:backups rl
negative:
 system:evilusers rlidwka

]]></artwork>
</figure>

<t>Thus, any time an access check is done on an ACL anywhere in the
volume: after we do the normal directory ACL check, we look at this
volume-level ACL. If the accessing user is in system:backups, they
will get rl rights, and if they are in system:evilusers, all of their
rights will go away.</t>

<section title="How do I prevent system:anyuser/system:authuser write access?">

<t>To prevent system:anyuser from having write access, we will need to
allow specifying the 'anonymous' user in the volume-level ACL, which
refers only to unauthenticated accesses. Then, you just give negative
write rights to the anonymous user. The command would look something
like:</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos setacl -vol user.adeason -acl anonymous idwka -neg

]]></artwork>
</figure>

<t>For system:authuser, you cannot prevent write access with this method.
It is a limitation of this approach. (Giving system:authuser negative
idwka rights would revoke those rights from _all_ authenticated users,
which is probably not what you want to do.)</t>

</section>

<section title="How do I ensure nobody in group.foo gets write access?">

<t>Just grant negative idwka access to group.foo on the volume. Something
like:</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos setacl -vol user.adeason -acl group.foo idwka -neg

]]></artwork>
</figure>

<t>Members of group.foo will now not be able to write anything in the
volume.</t>

</section>

<section title="How do I guarantee group.bar read access?">

<t>Same as above, just grant positive read rights. Something like:</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos setacl -vol user.adeason -acl group.bar rl

]]></artwork>
</figure>

</section>

<section title="Method A advantages">

<t>
  <list style="symbols">
    <t>Changing the volume-level rights is quick.</t>

    <t>Minimal end-administrator confusion; this is relatively simple to
       understand.</t>
 
    <t>Simpler than method C to implement.</t>
  </list>
</t>

</section>

<section title="Method A disadvantages">

<t>
<list style="symbols">
<t>We have no way to restrict access of special groups like
   system:authuser or host IP groups. To get this, we'd have to combine
   with method with method B or C.</t>
 
<t>There is no way to override the volume-level ACL, and have an
   administrator force e.g. system:anyuser write access on a particular
   directory.</t>
 
<t>Higher end-user confusion. With legacy 'fs listacl', there is no way
   to see that there is a volume-level ACL in play, and users may have
   no idea why access is failing for certain cases. Of course, releasing
   new tools can fix that.</t>
 
<t>Performance impact is an extra O(n) ACL calculation for the
   volume-level ACL overlay in the critical path. But those ACLs should
   be small anyway.</t>
</list>
</t>

</section>

</section>

<section anchor="methodb" title="Method B: volume ACL masks">

<t>With this method, we maintain a mapping of users to a rights mask. Any
time an ACL access check is performed, if a positive ACL entry matches a
user in that table, the acquires rights are masked to the rights mask in
the table.</t>

<t>For example, if we wanted to prevent users from giving away write access
to system:anyuser, and prevent users from giving admin access to
system:authuser, we could have a table like so:</t>

<figure align="center">
<artwork align="left"><![CDATA[

system:anyuser rl
system:authuser rlidwk

]]></artwork>
</figure>

<t>So any time an ACL entry for system:anyuser appears, everything is
treated as if the rights in that ACL entry were logically ANDed with
'rl'. So no user can gain more than 'rl' rights on a directory simply by
being in system:anyuser.</t>

<section title="How do I prevent system:anyuser/system:authuser write access?">

<t>Set the rights mask for them to just 'rl'. Something like:</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos setaclmask -vol user.adeason -user system:anyuser -mask rl

]]></artwork>
</figure>

<t>So any time an ACL entry for system:anyuser appears in the volume,
everything will act as if the rights were limited to rl.</t>

</section>

<section title="How do I ensure nobody in group.foo gets write access?">

<t>You cannot _prevent_ access for an arbitrary group with this method, but
you can make it harder to do accidentally. You can set the rights mask
like so:</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos setaclmask -vol user.adeason -user group.foo -mask rl

]]></artwork>
</figure>

<t>Which restricts any rights for group.foo on any ACL to be restricted to
'rl'. However, a user can intentionally work around this by simply
placing group.foo in another group:</t>

<figure align="center">
<artwork align="left"><![CDATA[

  pts creategroup adeason:foo
  pts adduser group.foo adeason:foo
  fs setacl $DIR adeason:foo rlidwka

]]></artwork>
</figure>

<t>Since group.foo itself never apears in the ACL, the ACL mask is
bypassed.</t>

</section>

<section title="How do I guarantee group.bar read access?">

<t>You cannot. This method cannot grant additional rights.</t>

</section>

<section title="Method B advantages">

<t>
<list style="symbols">
<t>Changing the rights mask is quick.</t>

<t>Runtime performance overhead in the critical path is O(1).</t>
</list>
</t>

</section>

<section title="Method B disadvantages">

<t>
<list style="symbols">
<t>Not as useful for non-'special' groups. That is, it can be trivially
   worked around, unless you only use this for groups like
   system:anyuser, system:authuser, or host IP groups.</t>
 
<t>No way to override the ACL masks on a particular directory, if the
   administrator wants to.</t>

<t>Higher end-user confusion with legacy client tools. There's no way to
   see what the ACL rights are restricted to until newer client tools
   are deployed.</t>
</list>
</t>

</section>

</section>

<section title="Method C: volume ACL policies">

<t>With this method, we maintain policies of who is allowed to set what
ACLs in a volume. That is, unlike methods A and B, we perform additional
access checks at SetACL time, not at the time when the files are
accessed. We would have 4 volume-level ACLs that define what users are
allowed to add positive rights ('add-positive'), remove positive rights
('remove-positive'), add negative rights ('add-negative'), and remove
negative rights ('remove-negative').</t>

<t>For example, to allow nobody but system:powerusers to grant idwka rights
to system:anyuser, we'd have a policy for system:anyuser that would look
like this:</t>

<figure align="center">
<artwork align="left"><![CDATA[

add-positive:
  system:powerusers rlidwka
  system:anyuser    rl

]]></artwork>
</figure>

<t>After that policy is set, any time a user not in system:powerusers tries
to grant system:anyuser more than rl rights, they will get an EACCES
error. This does not change the existing ACLs in the volume; an
administrator will need to run an auditing tool to make sure that
existing ACLs comply with the volume policy.</t>

<section title="How do I prevent system:anyuser/system:authuser write access?">

<t>You would call something like this</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos setpolicy -add-positive \
    -user system:anyuser      \
    -set-rights rl            \
    -for-user system:anyuser  \
    -in-volume user.adeason

]]></artwork>
</figure>

<t>to prevent people from giving system:anyuser write access. To ensure
that existing ACLs don't permit write access, you would need to run
something like</t>

<figure align="center">
<artwork align="left"><![CDATA[

  vos auditpolicy -vol user.adeason

]]></artwork>
</figure>

</section>

<section title="How do I ensure nobody in group.foo gets write access?">

<t>To prevent an arbitrary normal group from getting write access, things
are slightly different. You would need to prevent users from taking away
negative idwka rights, and then assign negative idwka rights to all
directories in the volume. So, something like</t>

<figure align="center">
<artwork align="left"><![CDATA[

 vos setpolicy -remove-negative \
   -user system:anyuser         \
   -set-rights rl               \
   -for-user group.foo          \
   -in-volume user.adeason

]]></artwork>
</figure>

<t>Would allow users to only remove 'rl' rights from group.foo in negative
ACLs. Then you would need to set negative idwka ACLs on all directories
in the volume.</t>

</section>

<section title="How do I guarantee group.bar read access?">

<t>Prevent normal users from taking away read access from group.bar, and
from granting negative read access for group.bar:</t>

<figure align="center">
<artwork align="left"><![CDATA[

 vos setpolicy -remove-positive \
   -user system:anyuser         \
   -set-rights idwka            \
   -for-user group.bar          \
   -in-volume user.adeason
 
 vos setpolicy -add-negative \
   -user system:anyuser      \
   -set-rights idwka         \
   -for-user group.bar       \
   -in-volume user.adeason

]]></artwork>
</figure>

<t>Then, grant read access for group.bar in all directories in the volume.</t>

</section>

<section title="Method C advantages">

<t>
<list style="symbols">
<t>More flexible for a variety of situations. In particular, this allows
   administrators (or an arbitrary administrator-defined set of users)
   to override the volume policies, and set e.g. system:anyuser write on
   a particular directory if they so wish.</t>

<t>No performance overhead at access-check time. All of the additional
   access checks are done during SetACL.</t>
 
<t>Minimal end-user confusion. ACLs accurately represent exactly what
   rights different users have. Trying to set an ACL that violates the
   policy will result in EACCES, so they know the SetACL operation
   didn't work. It may be confusing as to why it did not, but at least
   it is clear that the ACL was not changed.</t>
</list>
</t>

</section>

<section title="Method C disadvantages">

<t>
<list style="symbols">
<t>Volumes need to be 'audited' (or all of the ACLs just need to be set)
   to make sure they comply with the ACL policy, which can be very slow.</t>
 
<t>Higher end-administrator confusion. This by far the most confusing
   method for administrators to set ACL policies.</t>
</list>
</t>

</section>

</section>

</section>

<section title="Summary">

<t>As I mentioned, we could just do all of these, since they are
potentially best suited to different scenarios. Either method C by
itself or methods A and B together do seem to cover most of the
immediately-apparent use cases, though. To summarize the general areas
in which the different methods are better or worse:</t>

<figure align="center">
<artwork align="left"><![CDATA[

                     Better     | Worse
                     ---------------------
flexibility:       : method C   | method A+B
end-user confusion : method C   | method A+B
end-admin confusion: method A+B | method C
policy-change speed: method A+B | method C

]]></artwork>
</figure>

<t>There are other pros and cons, but I think those areas are the only ones
where it matters much. If you see any problems that aren't listed here,
or if you particularly want one of the described methods, please let us
know.</t>

</section>

    <section anchor="Acknowledgements" title="Acknowledgements">
      <t>
        The authors would like to thank Jim Rowan for discussing problematic 
        interactions between the proposed ACL policy management techniques 
        and PTS user-managed groups, and Jeffrey Altman for helping to better
        frame the problem statement and proposing alternative implementations.
      </t>
    </section>

    <!-- Possibly a 'Contributors' section ... -->

    <section anchor="IANA" title="IANA Considerations">
      <t>This memo includes no request to IANA.</t>
    </section>

    <section anchor="Security" title="Security Considerations">
      <t>
        The existing security model is known to be flawed.  This draft
        attempts to improve the situation by limiting the extent to which
        end users can modify file system permissions.  However, it is known
        that this is not sufficient to address all possible ACL attack vectors.
        Two key areas of concern are authorization for modification of policy
        metadata, and interaction with user-managed PTS groups.
      </t>

      <t>
        How modification of policy data will be authorized in an environment
        using RBAC is not clear; it is known that system:administrators is
        not always the appropriate group of principals.  In highly
        secured environments there may be a desire to restrict modification of
        policy to a security-related group, rather than the group responsible for
        maintaining the AFS server plant.  This is not addressed in the
        memo, although it could be addressed by means of additional per-volume
        metadata.
      </t>

      <t>
        There are proposed attack vectors by which a user-managed group can be used
        to get around ACL restrictions.  While these attacks can bypass a naive
        ACL policy specification, it is possible to circumvent these techniques through
        the use of negative access control policy entries.
      </t>
    </section>
  </middle>

  <!--  *****BACK MATTER ***** -->

  <back>
    <!-- References split into informative and normative -->

    <!-- There are 2 ways to insert reference entries from the citation libraries:
     1. define an ENTITY at the top, and use "ampersand character"RFC2629; here (as shown)
     2. simply use a PI "less than character"?rfc include="reference.RFC.2119.xml"?> here
        (for I-Ds: include="reference.I-D.narten-iana-considerations-rfc2434bis.xml")

     Both are cited textually in the same manner: by using xref elements.
     If you use the PI option, xml2rfc will, by default, try to find included files in the same
     directory as the including file. You can also define the XML_LIBRARY environment variable
     with a value containing a set of directories to search.  These can be either in the local
     filing system or remote ones accessed by http (http://domain/dir/... ).-->

    <references title="Normative References">
      <!--?rfc include="http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml"?-->
      &RFC2119;

    </references>

 <!--
   <references title="Informative References">
      <reference anchor="AFS3-FSCM">
        <front>
          <title>AFS-3 Programmer's Reference: File Server/Cache Manager Interface</title>

          <author initials="E.R." surname="Zayas" fullname="Edward R. Zayas">
            <organization abbrev="Transarc">Transasrc Corporation</organization>
          </author>

          <date year="1991" month="August" day="20" />
        </front>
        <seriesInfo name="Tech. Rep." value="FS-00-D162" />
      </reference>
    </references>
  -->
  </back>
</rfc>
