RFC: Altering the processing of IPv4 (aka Host) ACLs to enforce negative rights
Jeffrey E Altman <[email protected]> Mon, 20 Mar 2023 16:21:12 -0400
| Newsgroups | gmane.comp.file-systems.openafs.general |
|---|---|
| Organization | AuriStor, Inc. |
| Message-ID | <[email protected]> |
On 7 March Andrew Deason submitted a patch to OpenAFS documenting the
existing behavior of the OpenAFS fileserver when computing Anonymous and
Caller Access Rights if the IPv4 address from which the RXAFS RPC was
received matches a PTS host entry and that PTS entry matches an Access
Control Entry (ACE).
https://gerrit.openafs.org/#/c/15340/
Quoting Andrew's submission to the fs_setacl man page:
"Combining _Negative rights_ granted from machine entries (IP
addresses) and _Normal rights_ granted from non-machine entries (or
vice versa) will generally not work as expected. Permissions granted
by machine entries and by non-machine entries are calculated
separately, and both sets of permissions are given to an accessing
user. For example, if permissions are granted to an authenticated
user or group (or _system:anyuser_), you cannot remove those
permissions from specific hosts by adding machine entries to a group
in an ACL in the _Negative rights_> section."
The IBM AFS Administrator's Guide "Protecting Data in AFS" section states:
"When determining what type of access to grant to a user, theFile
Server first compiles a set of permissions by examiningall of the
entries in the Normal rights section of the ACL. Itthen subtracts
any permissions associated with the user (orwith groups to which the
user belongs) on the Negative rightssection of the ACL. Therefore,
negative permissions alwayscancel out normal permissions."
IBM/Transarc AFS 3.2 introduced the granting of permissions based upon
the host's IPv4 address in addition to those granted to the caller. The
implementation evaluates the caller's rights independently of the host's
rights and then ORs the results. This approach violates the statement
that negative permissions always cancel out normal (aka positive)
permissions. If a caller is granted "read" but there is a matching
negative "read" ACE (aka permission) for the host, the negative "read"
ACE is ignored. Likewise if "lookup" is granted to the host but the
caller matches a negative "lookup" ACE, then the caller's negative
"lookup" ACE is ignored.
The problem can be demonstrated with a couple of examples. First, lets
define some PTS entities and membership relations:
* user: jane = 1000
o member: system:authusers
o member: system:anyuser
o member: no-admin
* user: 128.66.0.130 = 2000
o member: local-hosts
* group: no-admin = -100
o member: jane
* group: local-hosts = -500
o member: 128.66.0.130
Example 1: RXAFS RPC received from a host that is not a member of
local-hosts
ACL
* system:anyuser: l; -none
* system:authuser: lrk; -none
* jane: none; -r
* local-hosts: r; -none
Rights:
* system:anyuser: lookup
* system:authuser: lookup, read, lock
* jane: lookup, lock
When "jane" accesses a file with this ACL the granted rights will be
"lk" because the negative read permission cancels the positive read
permission granted by the membership in the system:authuser group.
Example 2: RXAFS RPC received from a host that is a member of local-hosts
ACL
* system:anyuser: l; -none
* system:authuser: lrk; -none
* jane: none; -r
* local-hosts: r; -none
Rights:
* system:anyuser: lookup, read
* system:authuser: lookup, read, lock
* jane: lookup, read, lock
In this case, even though "jane" is denied the "read" permission granted
to members of "system:authuser" because of the negative "read" in the
"jane" ACE she is granted the permission because of the positive read
permission granted to "local-hosts" members. The granting of "read"
permission to "jane" is an unexpected result!
Example 3: RXAFS RPC received from a host that is not a member of
local-hosts
ACL
* system:anyuser: l; -none
* system:authuser: lrk; -none
* jane: lrkwid; -none
* local-hosts: none; -wida
Rights:
* system:anyuser: lookup
* system:authuser: lookup, read, lock
* jane: lookup, read, lock, write, insert, delete
In this case, "jane" is granted all of the permissions other than "admin".
Example 4: RXAFS RPC received from a host that is a member of local-hosts
ACL
* system:anyuser: l; -none
* system:authuser: lrk; -none
* jane: lrkwid; -none
* local-hosts: none; -wida
Rights:
* system:anyuser: lookup
* system:authuser: lookup, read, lock
* jane: lookup, read, lock, write, insert, delete
In this case, "jane" is granted all of the permissions other than
"admin". However, because the RPC was issued from a host that is a
member of "local-hosts" the expected result would be "jane" receiving
only the "lookup, read, lock" rights. The granting of "write, insert
and delete" permission is an unexpected outcome!
In examples 2 and 4 rights are granted to the caller that would appear
to be contrary to the explicit use of negative rights in the access
control entries. The example 4 use case might represent client systems
which are intended to be read-only consumers of the /afs content but
which might be vulnerable to exploitation. Example 2 is intended to
always deny read privileges to "jane" but if she can gain access to the
host with IPv4 address 128.66.0.130 she can bypass those restrictions.
This behavior feels like a bug to me. A bug that has been present since
the release of AFS 3.2 more than thirty years ago but a bug
nevertheless. I propose that OpenAFS fix the broken behavior so that
ACL interpretation is consistent with the documentation inherited from IBM.
Two commits submitted to Gerrit will enforce negative access rights.
https://gerrit.openafs.org/#/c/15344/
https://gerrit.openafs.org/#/c/15345/
History:
AFS 3.1 and earlier did not have a concept of IP or Host ACLs. That
functionality was introduced in AFS 3.2. However, the implementation
that is present in the release version of AFS 3.2 and in use to this day
might not have been the original implementation. Today's fileserver
issues separate calls to the protection service to obtain the caller's
Current Protection Set (CPS) and the host's CPS. The fileserver then
computes the caller rights by comparing the caller's CPS to the object's
ACL; and it computes the host's rights by comparing the host's CPS to
the object's ACL. The fileserver then grants the caller all rights
granted to both the caller and the host.
The host's CPS is obtained by the fileserver by issuing the
PR_GetHostCPS RPC. PR_GetHostCPS differs from PR_GetCPS in that it
matches the host's IPv4 address using wildcard pattern matching when
searching for a matching PTS ID. It also does not treat the PTS entity
as a member of the system:anyuser group.
Before PR_GetHostCPS was added to the protection service another RPC was
introduced, PR_GetCPS2 which obtained the CPS for the combination of a
caller and a host. An implementation of IP ACLs that used PR_GetCPS2
would have behaved as expected because the all of the positive rights
would have been computed and from those all of the negative rights would
have been removed. I do not have access to the source code for a
version of the fileserver that used the PR_GetCPS2 RPC but I can imagine
that a likely implementation would have issued a PR_GetCPS2 call for
(anonymous, host) and (caller, host). The additional load these RPCs
placed on the protection service might have been deemed too expensive.
As a result, the alternative approach using the PR_GetHostCPS was
introduced.
Whatever the motivation for PR_GetHostCPS in preference to PR_GetCPS2,
the existing implementation does not interpret ACLs in a manner that
permits negative rights to be superior to positive rights. Perhaps it
didn't occur to the implementer that there was a problem; and it didn't
occur to anyone that a simple change to acl_checkRights() and the
fileserver GetRights() function would permit computing the expected results.
Proposal:
I propose that OpenAFS treat the current behavior as a bug. The use of
negative rights is discouraged because they are hard to analyze. It is
hoped that their use is rare. If negative rights are not in use, then
changing the behavior when IP ACLs exist will not alter the computed
outcome. However, if negative rights are in use, they are likely being
used because it wasn't easy to limit the access any other way. In which
case, granting more access then was specified is problematic. A CVE
can be published to document the existing behavior and the behavior as
it will appear beginning with a specific version of the fileserver.
If required, a configuration option can be provided to enable the AFS
3.2 behavior until all of the fileservers within a cell have been
updated. I discourage using a configuration option to enable the
stricter interpretation of ACLs as that will result in some sites being
vulnerable when they did not intend to be.
Jeffrey Altman
P.S. I am writing this letter publicly as opposed to sending it to the
openafs-security queue because the behavior in question is public and
Andrew's proposed patch to the OpenAFS man pages is public.
smime.p7s
(application/pkcs7-signature, 3.9 KB) - not displayed